BZOJ1951 Sdoi2010 古代豬文

盧卡斯定理例題。 

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll p=999911659;
const int N=1e5+5;
void exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b) 
    {
        x=1,y=0;
        return;
    }
    exgcd(b,a%b,y,x);
    y-=(a/b)*x;
}
ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=a*res%p;
        b>>=1;
        a=a*a%p;
    }
    return res;
}
ll mod[4]={2,3,4679,35617},q,n;
ll jc[4][N],jc_inv[4][N];
void init()
{
    for(int i=0;i<4;i++)
    {
        jc[i][0]=jc[i][1]=1;
        jc_inv[i][0]=jc_inv[i][1]=1;
        for(int j=2;j<mod[i];j++)
        {
            jc[i][j]=jc[i][j-1]*j%mod[i];
            ll x,y;
            exgcd(jc[i][j],mod[i],x,y);
            jc_inv[i][j]=((x%mod[i])+mod[i])%mod[i];
        }
    }
}
ll a[4]={0};
ll C(ll x,ll y,int i)
{return y>x?0:jc[i][x]*jc_inv[i][y]*jc_inv[i][x-y]%mod[i];}
ll cal(ll nn,ll d,int i)
{
    if(d<mod[i]&&nn<mod[i]) return C(nn,d,i);
    ll tmp=C(nn%mod[i],d%mod[i],i);
    return tmp==0?0:tmp*cal(nn/mod[i],d/mod[i],i%mod[i]);
} 
int main()
{
    scanf("%lld%lld",&n,&q);
    if(q==p) 
    {
        printf("0");
        return 0;
    }
    init();
    for(int i=1;i*i<=n;i++) 
        if(n%i==0)
            for(int j=0;j<4;j++) 
            {
                a[j]=(a[j]+cal(n,i,j))%mod[j];
                if(i*i==n) continue;
                a[j]=(a[j]+cal(n,n/i,j))%mod[j];
            }
    ll M=p-1,sum=0,x,y;
    for(int i=0;i<4;i++)
    {
        exgcd(M/mod[i],mod[i],x,y);
        sum+=a[i]*M/mod[i]*x;
    }
    sum=(sum%M+M)%M;
    printf("%lld",qpow(q,sum));
    //system("pause");
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章