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;} 

完结撒花

posted @ 2018-10-15 16:53  ASDIC减除  阅读(144)  评论(0编辑  收藏  举报