解题思路:对于这个问题,首先我们要通过快速幂求出n=x^x%1000的值,下面就是找出满足a1+a2+……+ak=n(a1....ak为未知量)的解的组数,这里我们可以采用组合计数中常用的一个方法——隔板法来求得,我们假设有n个小球排成一列,目的是通过加隔板的方式将这些球分成k组,n个小球之间一共有n-1个空隙,我们要做的就是要在这n-1个空隙中添加k-1个隔板(2个隔板不能放在同一个位置),很容易想到就是求C(n-1,k-1),可以 C(n,k)=C(n-1,k-1)+C(n-1,k)来递推计算,采用然而很不幸的是1000!/(100!*900!)最多会有130多位数的结果,所以我们还需要手写下高精度加法,最后从最高一位非0的数开始一位一位输出即可。
上代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=150;
int f[1010][110][N];//这里x的第3维表示f[i][j]的每一位
int k,x;
int qmi(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=res*a%1000;
a=a*a%1000;
b>>=1;
}
return res;
}
void add(int a[],int b[],int c[])
{
for(int i=0,t=0;i<N;i++)
{
t=(t+b[i]+c[i]);
a[i]=t%10;
t/=10;
}
}
int main()
{
cin>>k>>x;
int n=qmi(x%1000,x%1000);//这里的x要模一下1000,不然算出来的n结果不对
//求C(n-1,k-1)
for(int i=0;i<n;i++)
for(int j=0;j<k&&j<=i;j++)
if(j==0)
f[i][j][0]=1;
else
add(f[i][j],f[i-1][j-1],f[i-1][j]);
int i=N-1;
int *g=f[n-1][k-1];
while(g[i]==0&&i>=0)//相当于去掉前导零
i--;
while(i>=0)
cout<<g[i--];
return 0;
}