【JZOJ5330】【NOIP2017提高A组模拟8.22】密码【51nod1569】二项式系数的个数

来源:互联网 发布:js 中国地图 编辑:程序博客网 时间:2024/06/11 02:42

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

首先有个库默尔定理:设m,n为正整数,p为素数,则Cmm+n含p的幂次等于m+n在p进制下的进位次数。
于是我们就很好办了,显然当k大于n在p进制下的位数答案为0。我们只要满足(l-s)+s的进位次数大于等于k即可。我们将n转化为p进制下。设f[i][j][k][0..1][0..1]位当前dp到p进制第i位,进位次数为j,下一位是否仅为进位,前i位是否与N在p进制下相同的方案。转移有点多。

Code

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define ll long longusing namespace std;const ll maxn=4e3+5,mo=1e9+7;int f[maxn][maxn][2][2],a[maxn],b[maxn],c[maxn];ll n,p,q,i,t,j,k,l,x,y,z,ln,ln1,ans;char s[maxn];void make(){    ll i,j,k,x=0;    for (i=1;i<=c[0];i++){        c[i]+=x*10;        x=c[i]%p;c[i]/=p;    }    j=1;b[b[0]]=x;    while (j<=c[0] && !c[j]) j++;    if (j>c[0]) c[0]=0;    else{        for (i=j;i<=c[0];i++)            c[i-j+1]=c[i];        c[0]-=j-1;    }}int main(){    freopen("password.in","r",stdin);freopen("password.out","w",stdout);    scanf("%s%d%d",s+1,&p,&q);n=strlen(s+1);    for(i=1;i<=n;i++)c[i]=s[i]-48;c[c[0]]=n;    while (c[0])        b[0]++,make();    if (b[0]<q){        printf("0\n");return 0;    }    f[b[0]+1][0][0][1]=1;ln=p*(p+1)/2%mo;ln1=p*(p-1)/2%mo;    for (i=b[0]+1;i>1;i--){        x=b[i-1];        k=(x+1)*x/2%mo;l=x*(x-1)/2%mo;t=((x-1)*x/2+x*(p-x))%mo;y=(x*(x-1)/2+x*(p-x+1))%mo;        for (j=0;j<=b[0]-i+1;j++){            if (f[i][j][0][0]){                f[i-1][j][0][0]=(f[i-1][j][0][0]+f[i][j][0][0]*ln%mo)%mo;                f[i-1][j+1][1][0]=(f[i-1][j+1][1][0]+f[i][j][0][0]*ln1%mo)%mo;            }            if (f[i][j][1][0]){                f[i-1][j][0][0]=(f[i-1][j][0][0]+f[i][j][1][0]*ln1%mo)%mo;                f[i-1][j+1][1][0]=(f[i-1][j+1][1][0]+f[i][j][1][0]*ln%mo)%mo;            }            if (f[i][j][0][1]){                f[i-1][j][0][0]=(f[i-1][j][0][0]+f[i][j][0][1]*k%mo)%mo;                f[i-1][j][0][1]=(f[i-1][j][0][1]+f[i][j][0][1]*(x+1)%mo)%mo;                f[i-1][j+1][1][0]=(f[i-1][j+1][1][0]+f[i][j][0][1]*l%mo)%mo;                f[i-1][j+1][1][1]=(f[i-1][j+1][1][1]+f[i][j][0][1]*x%mo)%mo;            }            if (f[i][j][1][1]){                f[i-1][j][0][0]=(f[i-1][j][0][0]+f[i][j][1][1]*t%mo)%mo;                f[i-1][j+1][1][0]=(f[i-1][j+1][1][0]+f[i][j][1][1]*y%mo)%mo;                f[i-1][j][0][1]=(f[i-1][j][0][1]+f[i][j][1][1]*(p-x-1)%mo)%mo;                f[i-1][j+1][1][1]=(f[i-1][j+1][1][1]+f[i][j][1][1]*(p-x)%mo)%mo;            }        }    }    ans=0;    for (i=q;i<=b[0];i++)        ans=(ans+(f[1][i][0][0]+f[1][i][0][1])%mo)%mo;    printf("%lld\n",ans);}
阅读全文
1 0