BZOJ1951 SDOI2010 古代猪文 Lucas+CRT+逆元
题意:求${G^{\sum\limits_{d|N} {C_N^d} }}\bmod P$
题解:
设\[A = \sum\limits_{d|N} {C_N^d} = A\bmod (P - 1) + k(P - 1)\]
由费马小定理,G^A可以直接把k(P-1)省略掉,因此问题变成求G^[A%(P-1)] mod P将P-1质因分解得到2,3,4679,35617然后将A看作未知数,先用Lucas得到四个同余方程
\[\left\{ \begin{array}{l}
A \equiv {a_1}(\bmod 2)\\
A \equiv {a_2}(\bmod 3)\\
A \equiv {a_3}(\bmod 4679)\\
A \equiv {a_4}(\bmod 35617)
\end{array} \right.\]
CRT合并求出A,然后就是快速幂了。注意G=P的时候费马小定理不成立,输出0
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define ll long long const int MAXN=40000+2; const int P=999911658; const int M[]={0,2,3,4679,35617}; ll N,G,sum,a[5],cnt,fac[5][MAXN],ans; ll Quick_pow(ll a,ll b,ll p){ a%=p; ll t=(b&1?a:1); while(b>>=1){ a*=a,a%=p; if(b&1) t*=a,t%=p; } return t; } void Calc_fac(ll n,ll k){ fac[k][0]=1; for(int i=1;i<=n;i++) fac[k][i]=(fac[k][i-1]*i)%M[k]; } ll Calc_C(ll n,ll m,ll 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]; } ll Lucas(ll n,ll m,ll 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(ll a,ll b,ll &x,ll &y){ if(!b){ x=1,y=0; return; } exgcd(b,a%b,x,y); ll t=x; x=y,y=t-a/b*y; } ll Calc_ni(ll n,ll p){ ll 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; }