luogu 4345 Lucas的变形应用
求 sigma i由0-k C(n,i)
利用Lucas定理+整除分块将C(n/p,i/p)利用i/p分块,得到k/p-1个整块(p-1)和一个小块(k%p)
最后得到式子 F(n,k)=F(n/p,k/p-1)*F(n%p,p-1)+C(n/p,k/p)*F(n%p,k%p);
写代码时将F编写成类似与Lucas的递归程序
F(int n,int m) if(k<0) return 0; if(n==0&&k==0) return 1;
Lucas if(m==0) return 1; if(n==m) return 1;if(n<m) return 0;
#include<bits/stdc++.h> #define int long long #define rep(i,x,y) for(register int i=x;i<=y;i++) using namespace std; const int N=2500; const int p=2333; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;}int c[N][N],f[N][N]; inline void init(){ rep(i,0,2333) c[i][0]=1; rep(i,1,2333)rep(j,1,i) c[i][j]=(c[i-1][j]+c[i-1][j-1])%p; rep(i,0,2333) f[i][0]=1; rep(i,0,2333)rep(j,1,2333) f[i][j]=(f[i][j-1]+c[i][j])%2333;} inline int Lucas(int n,int m){ if(!m) return 1; if(n==m) return 1; if(n<m) return 0; return c[n%p][m%p]*Lucas(n/p,m/p)%p;} inline int F(int n,int k){ if(k<0) return 0; if(n==0||k==0) return 1; if(n<p&&k<p) return f[n][k]; return (F(n/p,k/p-1)*f[n%p][p-1]%p+Lucas(n/p,k/p)*f[n%p][k%p]%p)%p;} signed main(){init(); int T=read();while(T--){ int n=read(),k=read(); printf("%lld\n",F(n,k));} return 0;}
完结撒花