洛谷杂题

[SDOI2010]古代猪文

良心题,一题考了好几个数论知识
题意:求 \(G^{\sum\limits_{d|n}\dbinom{n}{d} }\%999911659\) 的值。
思路:
由欧拉定理可将问题转换为:\(\sum\limits_{d|n}\dbinom{n}{d}\%999911658\) 的值。
质数这么大,无法直接使用卢卡斯定理计算组合数。
考虑将 \(999911658\) 分解质因数,拆成 \(2\)\(3\)\(4679\)\(35617\) 四个质数。
对它们分别求出 \(\sum\limits_{d|n}\dbinom{n}{d}\) 模意义的值,设为 \(x1\)\(x2\)\(x3\)\(x4\)
可列方程组:

\[\begin{cases} ans\equiv x1&\mod 2\\ ans\equiv x2&\mod 3\\ ans\equiv x3&\mod 4679\\ ans\equiv x4&\mod 35617 \end{cases} \]

用 CRT 求解方程组,随后快速幂即可。
\(Code:\)

#include <bits/stdc++.h>
#define int long long
#define rgi register int
using namespace std;
const int M=1e5+7,inf=1e9+7,modd=999911658;
inline int read(){
	int w=0,r=1;char c=getchar();
	while(!(isdigit(c)||c=='-'))c=getchar();
	if(c=='-')r=-1,c=getchar();
	while(isdigit(c))w=w*10+c-'0',c=getchar();
	return w*r;
}
int n,g,d[M],tot,an[M];
int ksm(int x,int y,int m){
	int ans=1;
	while(y){
		if(y&1)ans=ans*x%m;
		x=x*x%m;
		y>>=1;
	}
	return ans;
}
int pri[4]={2,3,4679,35617},jc[M],jcinv[M],p;
void gitgud(int p){
	jc[0]=1;
	for(int i=1;i<=p;i++)jc[i]=jc[i-1]*i%p;
}
int C(int n,int m){
	if(n<0||n<m)return 0;
	if(n<p&&m<p)return jc[n]*ksm(jc[m],p-2,p)%p*ksm(jc[n-m],p-2,p)%p;
	return C(n%p,m%p)*C(n/p,m/p)%p;
}
int res;
void CRT(){
	res=0;
	for(int i=0;i<4;i++)res=(res+an[i]*(modd/pri[i])%modd*ksm(modd/pri[i],pri[i]-2,pri[i]))%modd;
}
signed main(){
	gitgud(100000);
	n=read(),g=read();
	if(g%(modd+1)==0){
		printf("0\n");
		return 0;
	}
	for(int cnt=0;cnt<4;cnt++){
		p=pri[cnt];
		gitgud(p);
		int ret=0;
		for(int i=1;i*i<=n;i++){
			if(n%i==0){
				an[cnt]=(an[cnt]+C(n,i))%p;
				if(n!=i*i)an[cnt]=(an[cnt]+C(n,n/i))%p;
			}
		}
	}
	CRT();
	printf("%lld\n",ksm(g,res,modd+1));
	return 0;
}
/*
4 2
*/
posted @ 2021-11-05 16:53  wcy2006  阅读(37)  评论(0)    收藏  举报