LG P2480 [SDOI2010]古代豬文
Description
豬王國的文明源遠流長,博大精深。
iPig 在大肥豬學校圖書館中查閱資料,得知遠古時期豬文文字總個數為 $n$。當然,一種語言如果字數很多,字典也相應會很大。當時的豬王國國王考慮到如果修一本字典,規模有可能遠遠超過康熙字典,花費的豬力、物力將難以估量。故考慮再三沒有進行這一項勞豬傷財之舉。當然,豬王國的文字後來隨著歷史變遷逐漸進行了簡化,去掉了一些不常用的字。
iPig 打算研究古時某個朝代的豬文文字。根據相關文獻記載,那個朝代流傳的豬文文字恰好為遠古時期的$\frac 1k$,其中 $k$是 $n$的一個正約數(可以是 $1$或 $n$)。不過具體是哪 $\frac 1k$,以及 $k$是多少,由於歷史過於久遠,已經無從考證了。
iPig 覺得只要符合文獻,每一種$k|n$都是有可能的。他打算考慮到所有可能的 $k$。顯然當 $k$等於某個定值時,該朝的豬文文字個數為 $\frac nk$。然而從 $n$個文字中保留下 $\frac nk$個的情況也是相當多的。iPig 預計,如果所有可能的 $k$的所有情況數加起來為$p$的話,那麼他研究古代文字的代價將會是 $g^p$。
現在他想知道豬王國研究古代文字的代價是多少。由於 iPig 覺得這個數字可能是天文數字,所以你只需要告訴他答案除以 $999911659$的餘數就可以了。
Solution
題目要求$g^{\sum{d|n\ C_n^d}}\ mod\ 999911659$
分類討論
當底數與模數互質時可以用尤拉定理推得
$$g^{\sum{d|n\ C_n^d}}\ mod\ 999911659=g^{\sum{d|n\ C_n^d\ mod\ 999911658}}\ mod\ 999911659$$
模數大得飛起,不能直接Lucas,於是質因數分解模數
$$999911659=2 \times 3 \times 4679 \times 35617$$
所以可以計算$\sum{d|n\ C_n^d}$模這四個數的值,用CRT求解方程組
$$\left\{\begin{matrix}
x \equiv a_1 & \mod 2\\
x \equiv a_2 & \mod 3\\
x \equiv a_3 & \mod 4679\\
x \equiv a_4 & \mod 35617
\end{matrix}\right. $$
解出$x$後快速冪求解
當底數與模數不互質時特判
#include<iostream> #include<cstdio> using namespace std; long long n,g,fac[]={0,2,3,4679,35617},a[10],jc[50005],inv[50005],ans; const long long mod=999911658; inline long long read() { long long f=1,w=0; char ch=0; while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { w=(w<<1)+(w<<3)+ch-'0'; ch=getchar(); } return f*w; } long long ksm(long long a,long long p,long long m) { long long ret=1; while(p) { if(p&1) { (ret*=a)%=m; } (a*=a)%=m; p>>=1; } return ret; } void pre(long long p) { jc[0]=1; for(long long i=1;i<=p;i++) { jc[i]=jc[i-1]*i%p; } } long long C(long long x,long long y,long long p) { if(x<y) { return 0; } return jc[x]*ksm(jc[y],p-2,p)%p*ksm(jc[x-y],p-2,p)%p; } long long lucas(long long x,long long y,long long p) { if(!x) { return 1; } return lucas(x/p,y/p,p)*C(x%p,y%p,p)%p; } void CRT() { for(long long i=1;i<=4;i++) { (ans+=a[i]*(mod/fac[i])%mod*ksm(mod/fac[i],fac[i]-2,fac[i])%mod)%=mod; } } int main() { n=read(); g=read(); if(!(g%(mod+1))) { puts("0"); return 0; } for(long long i=1;i<=4;i++) { pre(fac[i]); for(long long j=1;j*j<=n;j++) { if(!(n%j)) { (a[i]+=lucas(n,j,fac[i]))%=fac[i]; if(j*j!=n) { (a[i]+=lucas(n,n/j,fac[i]))%=fac[i]; } } } } CRT(); printf("%lld\n",ksm(g,ans,mod+1)%(mod+1)); return 0; }[SDOI2010]古代豬文