P2480 [SDOI2010]古代豬文 題解
阿新 • • 發佈:2020-10-23
0.0
刷的最後一道數論題,喔,一聲長嘆~
Link
今天還是來大致描述一下題面好了
給定\(q,n(1≤q,n≤10^9)\),計算 \(q^{\sum_{d|n}C^d_n}mod 999911659\)
Solve
先考慮特殊情況,如果 \(q\)是\(999911659\)的倍數,則答案為\(0\),否則,因為\(999911659\)是質數,所以\(q,n\)互質。由尤拉定理的推論得:
\[q^{\sum_{d|n}C^d_n} \equiv q^{\sum_{d|n}C^d_n\text{mod 999911659}} (\text{mod 999911659}) \]因此,我們計算 \(q^{\sum_{d|n}C^d_n\text{mod 999911659}}\)
嘗試分解質因數 $999911659=2 \ast 3 \ast 4679 \ast 35617 $。
然後列舉\(n\)的約數\(d\),運用\(Lucas\)定理求出組合數\(C^d_n\)。分別計算出\(\sum_{d|n}C^d_n\)對\(2,3,4679,35617\)四個質數取摸的結果,記為\(a_1,a_2,a_3,a_4\)。
最後用中國剩餘定理求解線性同餘方程組:
\(\begin{cases}\text{x mod 2}=a_1\\ \text{x mod 3}=a_2\\ \text{x mod 4679}=a_3\\ \text{x mod 35617}=a_4\\\end{cases}\)
即可得到\(\sum_{d|n}C^d_n\text{mod 999911659}\)的最小非負整數解 \(x\)。再用快速冪求出 \(q^x\)即可得到原問題的答案。
Code
#include<bits/stdc++.h> using namespace std; typedef long long LL; const LL mod=999911658; LL n,G,Fc[50005],a[5],b[5]={0,2,3,4679,35617},val; inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar(); return ret*f; } LL Pow(LL a,LL b,LL p){ LL w=a,s=1; while(b){ if(b&1)s=w*s%p; w=w*w%p; b>>=1; } return s; } void make_Fc(LL p){ Fc[0]=1; for(int i=1;i<=p;i++)Fc[i]=Fc[i-1]*i%p; return ; } LL C(LL n,LL m,LL p){ if(n<m)return 0; return Fc[n]*Pow(Fc[m],p-2,p)%p*Pow(Fc[n-m],p-2,p)%p; } LL Lucas(LL n,LL m,LL p){ if(n<m)return 0;if(!n)return 1; return Lucas(n/p,m/p,p)*C(n%p,m%p,p)%p; } void CRT(){ for(int i=1;i<=4;i++) val=(val+a[i]*(mod/b[i])%mod*Pow(mod/b[i],b[i]-2,b[i]))%mod; } int main(){ // freopen("P2480.in","r",stdin); // freopen("P2480.out","w",stdout); n=read();G=read(); if(G%(mod+1)==0){printf("0\n");return 0;} for(int k=1;k<=4;k++){ make_Fc(b[k]); for(int i=1;i*i<=n;i++){ if(n%i==0){ a[k]=(a[k]+Lucas(n,i,b[k]))%b[k]; if(i*i!=n){ a[k]=(a[k]+Lucas(n,n/i,b[k]))%b[k]; } } } } CRT(); printf("%lld\n",Pow(G,val,mod+1)); return 0; }