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 }
View Code

 

posted @ 2018-06-21 14:32  鲸头鹳  阅读(106)  评论(0编辑  收藏  举报