Description
佳佳碰到了一個難題,請你來幫忙解決。 對於不定方程a1+a2+……+ak-1+ak=g(x),其中k>=2且k∈N*,x是正整數,g(x)=xx mod 1000(即xx除以1000的餘數),x,k是給定的數。我們要求的是這個不定方程的正整數解組數。
舉例來說,當k=3,x=2時,分別爲(a1,a2,a3)=(2,1,1),(1,2,1),(1,1,2).
Input
輸入文件有且只有一行,爲用空格隔開的兩個正整數,依次爲k,x。
Output
輸出文件有且只有一行,爲方程的正整數解組數。
Sample Input
3 2
Sample Output
3
Data Constraint
【數據範圍】
對於40%的數據,ans<=1016;
對於100%的數據,k<=100,x<=231-1,k<=g(x)。
//written by zzy
題目大意:
求方程sum(a1…ak)=xx%1000的解的個數
題解:
對於g(x)用快速冪求
考慮解得個數
令g(x)=n,將n拆成n個1,因爲ai>0,所以即等價於n個球中放入k個盤裏,盤不能爲空。
ans=C(k-1,n-1)(組合數)
隔板法即證明:
n個球中放入k個盤裏,盤不能爲空。
放法爲C(k-1,n-1)
例:n=4,k=2
X X X X(球)
1 2 3(板)
即在三個板子裏挑1個插入
方案數爲C(1,3)
(參見組合數的定義C(m,n)等於從1…n中選出m個的數的方案數 等於n!/(m!(n-m)!) )
那麼考慮一般情況
即在n-1個板子裏挑k-1個插入
方案數爲C(k-1,n-1)
證畢。
至於如何求C
將n!和m!,(n-m)!分別分解質因數
冪相減,跑遍高精乘即可。
#include<bits/stdc++.h>
#define Mod 1000
#define N 1005
#define M 1000
using namespace std;
int num,k,x,i,j,n;
int a[N],p[N],ans[M];
bool b[N];
long long g(long long s)
{
if (s==1) return x;
long long ss=g(s/2)%Mod;
if (s&1) return (((ss*ss)%Mod)*x)%Mod;
else return (ss*ss)%Mod;
}
void chen(int x)
{
long long g=0,t;
for (int i=M;i>=1;i--)
{
if (i<M&&ans[i+1]==0) break;
t=ans[i];
ans[i]=(t*x+g)%1000000000;
g=(t*x+g)/1000000000;
}
}
int main()
{
scanf("%d%d",&k,&x);
k--;
n=g(x); n--;
memset(b,true,sizeof(b));
for (i=2;i<=n;i++)
{
if (b[i])
{
num++; a[num]=i;
for (j=1;j<=n/i;j++)
b[i*j]=false;
}
}
for (i=1;i<=num;i++) {
x=a[i];
while (x<=n) {
p[i]+=n/x; x*=a[i];
}
x=a[i];
while (x<=k) {
p[i]-=k/x; x*=a[i];
}
x=a[i];
while (x<=n-k) {
p[i]-=(n-k)/x; x*=a[i];
}
}
ans[M]=1;
for (i=1;i<=num;i++)
for (j=1;j<=p[i];j++)
chen(a[i]);
i=1;
while (ans[i]==0&&i<=M) i++;
printf("%d",ans[i]);
for (j=i+1;j<=M;j++) {
x=ans[j];
if (x<100000000) printf("0");
if (x<10000000) printf("0");
if (x<1000000) printf("0");
if (x<100000) printf("0");
if (x<10000) printf("0");
if (x<1000) printf("0");
if (x<100) printf("0");
if (x<10) printf("0");
printf("%d",ans[j]);
}
}