[SDOI2010]古代猪文

[SDOI2010]古代猪文
一道数学题。
题解回去补
flag++

#include <cstdio>
#include <cmath>
long long n,g;
long long prime[4]= {2,3,4679,35617};
const long long mod=999911659;
int x[4];
long long fac[55555],inv[55555];
long long lucas(long long N,long long M,long long P) {
    if(N<M){return 0;}
    if(N<P&&M<P) {return fac[N]*inv[M]%P*inv[N-M]%P;}
    return lucas(N%P,M%P,P)*lucas(N/P,M/P,P)%P;
}
long long work(long long p) {
    fac[0]=1;
    long long ans=0;
    for(int i=1; i<p; i++) fac[i]=fac[i-1]*i%p;
    inv[p-1]=p-1;
    for(int i=p-2;~i;i--) inv[i]=inv[i+1]*(i+1)%p;
    long long lim=sqrt(n);
    for(int i=1; i<=lim; i++) {
        if(n%i) continue;
        ans=(ans+lucas(n,i,p))%p;
        if(n/i==i)continue;
        ans=(ans+lucas(n,n/i,p))%p;
    }
    return ans;
}
int exgcd(int a,int b,long long &x,long long &y) {
    if(!b) {
        x=1,y=0;
        return a;
    }
    int ans=exgcd(b,a%b,x,y),t=x;
    x=y,y=t-a/b*y;
    return ans;
}
long long ksm(long long d,int z) {
    long long res=1;
    while(z) {
        if(z&1) res=res*d%mod;
        d=d*d%mod;
        z>>=1;
    }
    return res;
}
void China() {
    long long ans=0,xx,y;
    for(int i=0; i<4; i++) {
        long long t=(mod-1)/prime[i];
        exgcd(prime[i],t,xx,y);
        ans=(ans+y*t*x[i])%(mod-1);
        if(ans<0) ans+=(mod-1);
    }
    printf("%lld",ksm(g,ans));
}
int main() {
    scanf("%d%d",&n,&g);
    if(g%mod==0) {
        putchar('0');
        return 0;
    }
    for(int i=0;i<4;i++)
    x[i]=work(prime[i]);
    China();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9252624.html