1. 程式人生 > 實用技巧 >P2480 [SDOI2010]古代豬文 題解

P2480 [SDOI2010]古代豬文 題解

0.0

刷的最後一道數論題,喔,一聲長嘆~

Link

P2480 [SDOI2010]古代豬文

今天還是來大致描述一下題面好了

給定\(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;
}