BZOJ 1951 古代猪文

Posted on 2016-12-20 16:18  ziliuziliu  阅读(196)  评论(0编辑  收藏  举报

快速幂+枚举质因数+欧拉定理+lucas定理+CRT。

注意两点:

  1.if (n<m) C(n,m)=0.

      2.这里0^0时应该return 0.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mod 999911659
#define mod2 999911658
#define maxn 40050
using namespace std;
long long g,n,p[10]={0,2,3,4679,35617},a[10],inv1[maxn],inv2[maxn];
long long f_pow(long long x,long long y,long long mods)
{
    x%=mods; 
    if ((!x) && (!y)) return 0;
    long long ans=1,base=x;
    while (y)
    {
        if (y&1) ans=(ans*base)%mods;
        base=(base*base)%mods;
        y>>=1;
    }
    return ans;
}
void get_table(long long x)
{
    inv1[0]=inv2[0]=1;
    for (long long i=1;i<=p[x]-1;i++)
    {
        inv1[i]=inv1[i-1]*i%p[x];
        inv2[i]=f_pow(inv1[i],p[x]-2,p[x]);
    }
}
long long comb(long long n,long long m,long long type)
{
    if (n<m) return 0;
    return inv1[n]*inv2[m]%p[type]*inv2[n-m]%p[type];
}
long long lucas(long long n,long long m,long long type)
{
    if (!m) return 1;long long ret=comb(n%p[type],m%p[type],type);
    return comb(n%p[type],m%p[type],type)*lucas(n/p[type],m/p[type],type)%p[type];
}
long long combines()
{
    long long ret=0;
    for (long long i=1;i<=4;i++)
        ret=(ret+a[i]*(mod2/p[i])%mod2*f_pow(mod2/p[i],p[i]-2,p[i])%mod2)%mod2;
    return ret;
}
long long ask()
{
    for (long long i=1;i<=4;i++)
    {
        get_table(i);long long top=(long long)(sqrt(n)+0.5);
        for (long long j=1;j<=top;j++)
        {
            if (!(n%j))
            {
                a[i]=(a[i]+lucas(n,j,i))%p[i];
                if (j*j!=n) a[i]=(a[i]+lucas(n,n/j,i))%p[i];
            }
        }
    }
    return combines();
}
int main()
{
    scanf("%lld%lld",&n,&g);
    printf("%lld\n",f_pow(g,ask(),mod));
    return 0;
}