BZOJ 4591: [Shoi2015]超能粒子炮·改 lucas定理
https://www.lydsy.com/JudgeOnline/problem.php?id=4591
https://blog.csdn.net/qq_33229466/article/details/78827788 推导过程见该博客
lucas定理就是 C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p
其实还挺简单的但是我wa了好几次因为最开始算前缀和没有算从0中选x个数的这一行,惨。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<bitset> 8 #include<queue> 9 using namespace std; 10 #define LL long long 11 const LL p=2333; 12 LL c[p+10][p+10]={},d[p+10][p+10]={}; 13 LL lucas(LL x,LL k){ 14 if(x==0||k==0)return 1; 15 return (lucas(x/p,k/p)*c[x%p+1][k%p+1])%p; 16 } 17 LL solve(LL x,LL k){ 18 if(k<0)return 0; 19 return ((solve(x/p,k/p-1)*d[x%p+1][p])%p+(lucas(x/p,k/p)*d[x%p+1][k%p+1])%p)%p; 20 } 21 int main(){ 22 c[1][1]=1;for(int j=1;j<=2335;++j)d[1][j]=(d[1][j-1]+c[1][j])%p; 23 for(int i=2;i<=2335;++i){ 24 for(int j=1;j<=i;++j)c[i][j]=(c[i-1][j]+c[i-1][j-1])%p; 25 for(int j=1;j<=2335;++j)d[i][j]=(d[i][j-1]+c[i][j])%p; 26 } 27 int T;scanf("%d",&T); 28 while(T-->0){ 29 LL x,k; 30 scanf("%lld%lld",&x,&k); 31 //if(k>x)k=x; 32 printf("%lld\n",solve(x,k)); 33 } 34 return 0; 35 }