方程的解
题目链接:
Description
佳佳碰到了一个难题,请你来帮忙解决。
对于不定方程 \(a1+a2+⋯+ak−1+ak=g(x)\),其中 \(k≥1\) 且 \(k∈N∗\),\(x\) 是正整数,\(g(x)=x^xmod1000\)(即 x 除以 1000 的余数),\(x,k\) 是给定的数。
我们要求的是这个不定方程的正整数解组数。
举例来说,当 \(k=3,x=2\) 时,方程的解分别为:
\(1:a_1=1,a_2=1,a_3=2;\)
\(2:a_1=1,a_2=2,a_3=1;\)
\(3:a_1=2,a_2=1,a_3=1;\)
Input
有且只有一行,为用空格隔开的两个正整数,依次为 \(k,x\)。
\(1≤k≤100,\)
\(1≤x<231,\)
\(k≤g(x)\)
Output
有且只有一行,为方程的正整数解组数。
Sample Input
3 2
Sample Output
3
题意
求k个大于0的数凑成\(x^x%1000\)的方案数之和
题解:
隔板法求解等式:\(a1+a2+⋯+ak−1+ak=n\)。可以用快速幂求出\(n=x^x%1000\)。我们把n想象成n个水平排列的小球,我们需要把这些小球用挡板分成k部分,每一部分都大于0。
\(eg:n=8,k=4\),我们可以在n-1个空隙中选择k-1插入挡板,第i个挡板的前面的小球数对应\(a_i\),第k-1个挡板后面的球数等于\(a_k\)
代码
#include<bits/stdc++.h>
using namespace std;
int qmi(int a,int b){
int res=1;
while(b){
if(b&1) res=1ll*res*a%1000;
b>>=1;
a=1ll*a*a%1000;
}
return res;
}
int f[1010][101][200];
void add(int a[],int b[],int c[]){
for(int i=0;i<199;++i){
a[i]+=b[i]+c[i];
a[i+1]+=(a[i])/10;
a[i]%=10;
}
}
int main(){
int k,x;
cin>>k>>x;
x=qmi(x,x);
if(x==0){
cout<<0<<endl;
return 0;
}
for(int i=0;i<=x;++i){
for(int j=0;j<k&&j<=i;++j)
if(!j)f[i][j][0]=1;
else add(f[i][j],f[i-1][j-1],f[i-1][j]);
}
int i=199;
while(f[x-1][k-1][i]==0&&i!=0) --i;
while(i>=0) cout<<f[x-1][k-1][i--];
return 0;
}