bzoj1902【Zju2116】 Christopher

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1902

sol  :一眼可以看出此题应用了lucas定理(逃~

   将n,m都化为p进制,记为a[],b[]

   则对于我们所求的C(n,m)%p,有C(n,m)=∏ (i from 1 to n) (p^i)*(C(a[i],b[i]))%p

   若C(n,m)为p的倍数,则存在某一位b[i]>a[i]

   即此题要求有多少个<n的数,且其p进制下存在某一位比n的p进制的对应位大

   求出a[]后直接数位dp即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int Mx=510;
struct Node
{
    int n,g[505];
    void pre(int k) {n=1; g[1]=k;}
    Node operator*(const int &b)
    {
        Node c; int y=0; c.n=n;
        if(!b) { c.pre(0); return c; }
        for(int i=1;i<=n;i++) { y+=g[i]*b; c.g[i]=y%10; y/=10; }
        while(y) { c.g[++c.n]=y%10; y/=10; }
        return c;
    }
    Node operator+(const Node &b)
    {
        Node c; int y=0,p;
        if(n>b.n)
        {
            c.n=n; for(int i=1;i<=n;i++) c.g[i]=g[i]; p=b.n;
            for(int i=1;i<=b.n;i++) { y+=b.g[i]+c.g[i]; c.g[i]=y%10; y/=10; }
            while(y&&p<n) { y+=c.g[++p]; c.g[p]=y%10; y/=10; }
        }
        else
        {
            c.n=b.n; for(int i=1;i<=b.n;i++) c.g[i]=b.g[i]; p=n;
            for(int i=1;i<=n;i++) { y+=g[i]+c.g[i]; c.g[i]=y%10; y/=10; }
            while(y&&p<b.n) { y+=c.g[++p]; c.g[p]=y%10; y/=10; }
        }
        if(y) c.g[++c.n]=y;
        return c;
    }
    int operator/(const int &b)
    {
        int y=0;
        for(int i=n;i>=1;i--)
        {
            y=y*10+g[i];
            if (y<b) g[i]=0;
            else {g[i]=y/b; y%=b;}
        }
        while(n>1&&!g[n]) n--;
        return y;
    }
    void read()
    {
        char s[Mx]; scanf("%s",s+1); n=strlen(s+1);
        for(int i=1;i<=n;i++) g[n+1-i]=s[i]-'0';
    }
} x,mul,ans,f[Mx];
int p,a[Mx],cnt;
int main()
{
    x.read(); scanf("%d",&p);
    while(x.n!=1||x.g[1]) a[++cnt]=x/p;
    f[0].pre(0),mul.pre(1),ans.pre(0);
    for(int i=1;i<cnt;i++)
    {
        f[i]=mul*(p-1-a[i]);
        f[i]=f[i]+f[i-1]*(a[i]+1);
        mul=mul*p;
    }
    for(int i=cnt;i>1;i--) ans=ans+f[i-1]*a[i];
    for(int i=ans.n;i>=1;i--) printf("%d",ans.g[i]);
    return 0;
}

 

posted @ 2017-03-16 00:50  Czarina  阅读(184)  评论(0编辑  收藏  举报