题目描述
佳佳碰到了一个难题,请你来帮忙解决。
对于不定方程a1+a2+…+ak-1+ak=g(x),其中k≥2且k∈N,x是正整数,g(x)=x^x mod
1000(即x^x除以1000的余数),x,k是给定的数。我们要求的是这个不定方程的正整数解组数。举例来说,当k=3,x=2时,分别为(a1,a2,a3)=(2,1,1)’(1,2,1),(1,1,2)。 输入输出格式 输入格式:
输入文件equation.in有且只有一行,为用空格隔开的两个正整数,依次为k,x。
输出格式:
输出文件equation.out有且只有一行,为方程的正整数解组数。
快速幂求出g(x)。
考虑裸的dp方程,dp[i][j]表示i个数和为j的方案数,dp[i][j]=Σdp[i-1][i-1…j-1],时间复杂度为O(k*mod^2)。
注意到边界条件dp[0][0]=1,其他所有值都由它推得,从刷表的角度考虑,dp[i][j]每次一定走到dp[i+1][j+x],最终要走到dp[k][g]。不妨看成要走k步,每一步可以走一个或一个以上的格子,最后总共要走g个格子,问方法总数。
这样就变成了计数问题,即要在(g-1)个间隔中选出(k-1)个,答案是c(g-1,k-1)。
注意使用高精度。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int bit=10000;
const int mod=1000;
struct NUM
{
int a[100],l;
NUM operator + (const NUM & x)
{
NUM ret;
ret.a[1]=0;
for (int i=1;i<=l||i<=x.l;i++)
{
ret.a[i]+=a[i]+x.a[i];
ret.a[i+1]=ret.a[i]/bit;
ret.a[i]%=bit;
}
ret.l=max(l,x.l);
if (ret.a[ret.l+1]) ret.l++;
return ret;
}
void out()
{
int i,j,k,x,y,z;
printf("%d",a[l]);
for (i=l-1;i;i--)
{
if (a[i]<10) printf("000");
else
{
if (a[i]<100) printf("00");
else
{
if (a[i]<1000) printf("0");
}
}
printf("%d",a[i]);
}
printf("\n");
}
}c[1010][110];
int pw(int x)
{
int base=x%mod,ans=1;
for (;x;x>>=1,base=(base*base)%mod)
if (x&1) ans=(ans*base)%mod;
return ans;
}
int main()
{
int i,j,k,m,n,p,q,x,y,z;
scanf("%d%d",&k,&x);
m=pw(x);
for (i=0;i<m;i++)
c[i][0].a[1]=c[i][0].l=1;
for (i=1;i<m;i++)
for (j=1;j<k;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
c[m-1][k-1].out();
}