BZOJ 1951 [SDOI2010]古代猪文 (组合数学+欧拉降幂+中国剩余定理)
题目大意:求$G^{\sum_{m|n} C_{n}^{m}}\;mod\;999911659\;$的值$(n,g<=10^{9})$
并没有想到欧拉定理..
999911659是一个质数,所以$\varphi(p)=p-1$
利用欧拉定理,降幂化简式子$G^{\sum_{m|n} C_{n}^{m}\;mod\;\varphi(p)}$
这样,指数部分可以用$Lucas$+中国剩余定理求解
然而..$G>10^9$很大,可能和模数$999911659$不互质!所以质数要额外加上$\varphi(p)$
1 #include <map> 2 #include <queue> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #define N 10100 8 #define ull unsigned long long 9 #define ll long long 10 #define maxn 36000 11 using namespace std; 12 13 ll n,g; 14 const ll m[]={2,3,4679,35617}; 15 16 ll qpow(ll x,ll y,const ll &mod){ 17 ll ans=1; 18 while(y){ 19 if(y&1) ans=(ans*x)%mod; 20 x=(x*x)%mod,y>>=1; 21 }return ans; 22 } 23 namespace excrt{ 24 ll exgcd(ll a,ll b,ll &x,ll &y){ 25 if(!b) {x=1,y=0;return a;} 26 ll ans=exgcd(b,a%b,x,y); 27 ll t=x;x=y,y=t-a/b*y; 28 return ans; 29 } 30 ll qadd(ll x,ll y,const ll &mod){ 31 ll ans=0; 32 while(y){ 33 if(y&1) ans=(ans+x)%mod; 34 x=(x+x)%mod,y>>=1; 35 }return ans; 36 } 37 ll ans=0,M=1; 38 void insert(ll A,ll B) 39 { 40 ll a=A,b=B,c=(a-ans%b+b)%b,x,y,g; 41 g=exgcd(M,b,x,y);b/=g; 42 //if(c/g!=0) return; 43 //x=qadd(x,c/g,b); 44 x=x*(c/g)%b; 45 ans+=x*M,M*=b,ans=(ans%M+M)%M; 46 } 47 }; 48 int son[N],d[N],ps[N],num,cnt; 49 namespace calc{ 50 ll mul[maxn+100],inv[maxn+100],minv[maxn+100]; 51 void Pre(const ll &mo) 52 { 53 mul[0]=mul[1]=inv[0]=inv[1]=minv[0]=minv[1]=1; 54 for(int i=2;i<mo;i++){ 55 mul[i]=mul[i-1]*i%mo; 56 inv[i]=1ll*(mo-mo/i)*inv[mo%i]%mo; 57 minv[i]=minv[i-1]*inv[i]%mo; 58 } 59 } 60 ll C(ll a,ll b,const ll &mo) 61 {return mul[a]*minv[b]%mo*minv[a-b]%mo;} 62 ll Lucas(ll a,ll b,const ll &mo) 63 { 64 if(b>a) return 0; 65 if(a<mo&&b<mo) return C(a,b,mo); 66 return Lucas(a/mo,b/mo,mo)*Lucas(a%mo,b%mo,mo)%mo; 67 } 68 ll solve(const ll &mo) 69 { 70 for(int i=2;i<mo;i++) 71 mul[i]=inv[i]=minv[i]=0; 72 Pre(mo);ll ans=0; 73 for(int i=1;i<=cnt;i++) 74 (ans+=Lucas(n,son[i],mo))%=mo; 75 return ans; 76 } 77 }; 78 void dfs_son(int i,ll s) 79 { 80 if(i>num) {son[++cnt]=s;return;} 81 for(int j=0;j<=d[i];j++) 82 dfs_son(i+1,s),s*=ps[i]; 83 } 84 void get_son(ll a) 85 { 86 int sq=sqrt(a); 87 for(int i=2;i<=sq;i++) 88 if(a%i==0){ 89 ps[++num]=i; 90 while(a%i==0) 91 d[num]++,a/=i; 92 } 93 if(a!=1) 94 ps[++num]=a,d[num]++; 95 dfs_son(1,1); 96 } 97 const ll smod=999911659; 98 99 int main() 100 { 101 scanf("%lld%lld",&n,&g); 102 get_son(n); 103 for(int i=0;i<4;i++) 104 { 105 ll ans=calc::solve(m[i]); 106 excrt::insert(ans,m[i]); 107 } 108 ll pw=excrt::ans; 109 ll ans=qpow(g,pw+smod-1,smod); 110 printf("%lld\n",ans); 111 return 0; 112 }