problem
Description
聪明的兔子定义了三个函数:
• g(x) 表示将x 十进制表示中各位数字从高位到低位降序排列组成的数字。
• l(x) 表示将x 十进制表示中各位数字从高位到低位升序排列组成的数字。
• f(x) = g(x) - l(x)
如果一个数x 与f(x) 相等,兔子们称它为幸运数。现在兔子们希望计算在所有的n 位数字中,所有幸运数的平方的和。结果对p 取模后输出,注意这里数字可以包含前导0.
Input
一行两个整数n 和p
Output
一行一个整数,表示所求的结果
Sample Input
4 10000
Sample Output
8276
Data Constraint
• 对于20% 的测试数据,1 <= n<= 10
• 对于100% 的测试数据,1 <= n <= 30, 1<= p<= 2* 10^9
analysis
正解dfs
因为n<=30,那么可以发现不进位且取了绝对值后原数是个回文串
如下图
所以我们就可以只搜索n的一半,另一半就出来了
然后把那个数字算出来,降序升序排完后再减一次判断是否与原数相等
相等就累加取平方中模并累加答案
数据不会超long long,放心用就好
code
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 35
using namespace std;
long long a[MAXN],f1[MAXN],f2[MAXN];
long long n,p,ans;
bool cmp(int x,int y)
{
return x>y;
}
void dfs(int x)
{
if (x>n/2)
{
if (n%2)a[n/2+1]=0;
for (int i=1;i<=n/2;i++)a[n-i+1]=-a[i];
for (int i=n;i>1;i--)
{
if (a[i]<0)
{
a[i]=a[i]+10;
a[i-1]--;
}
}
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
for (int i=1;i<=n;i++)f1[i]=f2[i]=a[i];
sort(f1+1,f1+n+1,cmp);
sort(f2+1,f2+n+1);
for (int i=n;i>=1;i--)
{
if (f1[i]<f2[i])
{
f1[i]+=10;
f1[i-1]--;
}
f1[i]-=f2[i];
}
bool bz=1;
for (int i=1;i<=n;i++)
{
if (a[i]!=f1[i])
{
bz=0;
break;
}
}
if (bz)
{
long long tot=0;
for (int i=1;i<=n;i++)tot=(tot*10+a[i])%p;
(ans+=tot*tot%p)%=p;
}
return;
}
for (int i=a[x-1];i>=0;i--)
{
a[x]=i;
dfs(x+1);
}
}
int main()
{
//freopen("readln.txt","r",stdin);
scanf("%lld%lld",&n,&p);
a[0]=9;
dfs(1);
printf("%lld\n",ans%p);
return 0;
}