51nod 1245 Binomial Coefficients Revenge kummer定理+数位dp

来源:互联网 发布:网络传播负面消息方法 编辑:程序博客网 时间:2024/06/14 01:34

题意

C(M,N) = M! / N! / (M - N)! (组合数)。给出M和质数p,求C(M,0), C(M,1)……C(M,M)这M + 1个数中,有多少数不是p的倍数,有多少是p的倍数但不是p^2的倍数,有多少是p^2的倍数但不是p^3的倍数……。
1 <= T <= 5000,2 <= M, P <= 10^18

分析

去学习了一发kummer定理,简称库默尔定理。大概就是说
这里写图片描述
这里写图片描述
然后就可以愉快的数位dp了。设f[i,j,0/1]表示从低到高做到第i位,进位了j次且该位是否进位的方案,转移显然。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;LL n,p,a[65],f[65][65][2];void solve(){    LL tmp=n;int a1=0;    while (tmp) a[++a1]=tmp%p,tmp/=p;    memset(f,0,sizeof(f));    f[0][0][0]=1;    for (int i=1;i<=a1;i++)    {        f[i][0][0]=f[i-1][0][0]*(a[i]+1);        for (int j=1;j<=a1;j++)        {            f[i][j][0]=f[i-1][j][0]*(a[i]+1)+f[i-1][j][1]*a[i];            f[i][j][1]=f[i-1][j-1][0]*(p-a[i]-1)+f[i-1][j-1][1]*(p-a[i]);        }    }    for (int i=0;i<=a1&&f[a1][i][0];i++) printf("%lld ",f[a1][i][0]);    puts("");}int main(){    int T;scanf("%d",&T);    while (T--)    {        scanf("%lld%lld",&n,&p);        solve();    }    return 0;}
原创粉丝点击