BZOJ1951 SDOI2010 古代猪文 Lucas+CRT+逆元

(P=999911659)

首先设A=sigma{C(d,N) | d|N}。

题目要求(G^A)%P

那么可以将A分成A%(P-1)+k*(P-1)。

G^A=G^(A%(P-1)+k*(P-1))=G^(A%(P-1))*G^(k*(P-1))。

根据费马小定理G^(P-1)≡1(mod P),那么G^A=G^(A%(P-1))*G^(k*(P-1))≡G^(A%(P-1))(mod P)

因此关键在于如何求出A%(P-1)。

首先求质因数用sqrt(N)枚举找一遍就好。

直接用Lucas求的话……除非你写高精。

将P-1质因分解为2*3*4679*35617。

那么就可以枚举算出A对以上四个数取余得到的余数,Lucas定理算出来。

那么可以得到四个同余方程:

A≡a1(mod 2)

A≡a2(mod 3)

A≡a3(mod 4679)

A≡a4(mod 35617)

中国剩余定理合并,求出A之后快速幂就好。

注意G==P的时候费马小定理不成立,输出0

别忘了long long

代码:


    #include <cstdio>  
    #include <cstring>  
    #include <cstdlib>  
    #include <iostream>  
    #include <algorithm>  
    using namespace std;  
      
    const int MAXN=40000+2;  
    const int P=999911658;  
    const int M[]={0,2,3,4679,35617};  
    long long N,G,sum,a[5],cnt,fac[5][MAXN],ans;  
      
    long long Quick_pow(long long a,long long b,long long p){  
        a%=p;  
        long long t=(b&1?a:1);  
      
        while(b>>=1){  
            a*=a,a%=p;  
            if(b&1) t*=a,t%=p;  
        }  
      
        return t;  
    }  
      
    void Calc_fac(long long n,long long k){  
        fac[k][0]=1;  
        for(int i=1;i<=n;i++) fac[k][i]=(fac[k][i-1]*i)%M[k];  
    }  
      
    long long Calc_C(long long n,long long m,long long k){  
        if(m>n) return 0;  
        return fac[k][n]*Quick_pow(fac[k][m]*fac[k][n-m],M[k]-2,M[k])%M[k];  
    }  
      
    long long Lucas(long long n,long long m,long long k){  
        if(!m) return 1;  
        return (Calc_C(n%M[k],m%M[k],k)*Lucas(n/M[k],m/M[k],k))%M[k];  
    }  
      
    void exgcd(long long a,long long b,long long &x,long long &y){  
        if(!b){  
            x=1,y=0;  
            return;  
        }  
      
        exgcd(b,a%b,x,y);  
      
        long long t=x;  
        x=y,y=t-a/b*y;  
    }  
      
    long long Calc_ni(long long n,long long p){  
        long long x,y;  
        exgcd(n,p,x,y);  
      
        return (x+p)%p;  
    }  
      
    int main(){  
        cin >> N >> G;  
      
        for(int i=1;i<=4;i++) Calc_fac(M[i],i);  
      
        if(G==P+1){  
            cout << 0 << endl;  
            return 0;  
        }  
      
        for(int i=1;i*i<=N;i++){  
            if(!(N%i)){  
                for(int j=1;j<=4;j++) a[j]+=Lucas(N,i,j),a[j]%=M[j];  
                if(i*i!=N) for(int j=1;j<=4;j++) a[j]+=Lucas(N,N/i,j),a[j]%=M[j];  
            }  
        }  
      
        for(int i=1;i<=4;i++) ans+=(((a[i]*Calc_ni(P/M[i],M[i]))%P)*(P/M[i]))%P,ans%=P;  
      
        cout << Quick_pow(G,ans,P+1) << endl;  
      
        return 0;  
    }  

你可能感兴趣的:(BZOJ1951 SDOI2010 古代猪文 Lucas+CRT+逆元)