【bzoj4591】[Shoi2015]超能粒子炮·改
设S(n,k)=Σ C(n,i) i=0..k
根据lucas定理可以得到
S(n,k) mod p = [ S(n/p,k/p-1)*S(n mod p,p-1)+C(n/p,k/p)*S(n mod p,k mod p) ] mod p
除法均向下取整
预处理0≤n,k<P的C,S值,根据上式递归计算
#include<cstdio> typedef long long lint; const int P=2333; int c[P][P],s[P][P],t; int C(lint n,lint k){ if(k<0||k>n)return 0; if(n<P)return c[n][k]; lint a=n/P,b=k/P; return C(a,b)*c[n%P][k%P]%P; } int S(lint n,lint k){ if(k<0)return 0; lint a=n/P,b=k/P; return (S(a,b-1)*s[n%P][P-1]+C(a,b)*s[n%P][k%P])%P; } inline void inc(int&a,int b){ a+=b; if(a>=P)a-=P; } inline lint input(){ lint x=0; int c=getchar(); while(c>57||c<48)c=getchar(); while(c>47&&c<58)x=x*10+c-48,c=getchar(); return x; } int main(){ c[0][0]=1; for(int i=0;i<P-1;i++){ for(int j=0;j<=i;j++){ inc(c[i+1][j],c[i][j]); inc(c[i+1][j+1],c[i][j]); } } for(int i=0;i<P;i++){ s[i][0]=c[i][0]; for(int j=1;j<P;j++)inc(s[i][j]=s[i][j-1],c[i][j]); } t=input(); while(t--){ lint a=input(),b=input(); printf("%d\n",S(a,b)); } return 0; }