(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; }