Luogu-2480 古代猪文

我们首先来概括一下题意,其实就是给定 \(n,g\),求:

\[g^{\sum_{k\nmid n} C_n^{\frac{n}{k}}}\operatorname{mod} 999911659 \]

如果 \(k\nmid n\),那么我们知道 \(\frac{n}{k}\cdot k=n\),所以原式转化为:

\[g^{\sum_{k\nmid n} C_n^k}\operatorname{mod} 999911659 \]

根据欧拉定理原式转化为:

\[g^{(\sum_{k\nmid n} C_n^k)\operatorname{mod} \varphi(999911659)}\operatorname{mod} 999911659 \]

由于 \(999911659\) 是一个质数,所以 \(\varphi(999911659)=999911658\)。原式可变为:

\[g^{(\sum_{k\nmid n} C_n^k)\operatorname{mod} 999911658}\operatorname{mod} 999911659 \]

很明显思路就是用 \(O(\sqrt{n})\) 的时间去找出 \(k\),然后快速求解组合数,很明显,Lucas 定理失效了,我们就需要进行一些问题的转化。我们可以对 \(999911658\) 进行质因数分解:\(999911658=2\times 3\times4679\times 35617\)。我们可以分别设:

\[\begin{cases}a_1={(\sum_{k\nmid n} C_n^k)\operatorname{mod} 2}\\a_2={(\sum_{k\nmid n} C_n^k)\operatorname{mod} 3}\\a_3={(\sum_{k\nmid n} C_n^k)\operatorname{mod} 4679}\\a_4={(\sum_{k\nmid n} C_n^k)\operatorname{mod} 35617}\end{cases} \]

用中国剩余定理(CRT)解决即可。

注意特判 \(g=mod\)

//#pragma GCC optimize("Ofast","-funroll-loops","-fdelete-null-pointer-checks")
//#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#include<bits/stdc++.h>
#define int long long
using namespace std;

int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch<'0'||ch>'9') {
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}

const int mod=999911659,b[]={0,2,3,4679,35617};

int n,jc[50010],a[10],g,m[5];

int qpow(int x,int y) {
	int ret=1;
	while(y) {
		if(y&1) {
			ret*=x;
			ret%=mod;
		}
		x=x*x%mod;
		y>>=1;
	}
	return ret;
}

void exgcd(int a,int b,int &x,int &y) {
	if(b==0) {
		x=1;
		y=0;
		return ;
	}
	exgcd(b,a%b,x,y);
	
	int x2=y;int y2=x-a/b*y;
	x=x2;y=y2;
}
int gcd(int a,int b) {
	return b==0? a:gcd(b,a%b);
}

int inv(int q,int p) {
	int x,y;
	int g=gcd(q,p);
	q/=g;p/=g;
	exgcd(q,p,x,y);
	return (x+p)%p;
}

int calc(int n,int m,int p) {
	if(m>n) {
		return 0;
	}
	return jc[n]*inv(jc[m],p)%p*inv(jc[n-m],p)%p;
}

int c(int n,int m,int p) {
	if(m==0) {
		return 1;
	}
	return c(n/p,m/p,p)*calc(n%p,m%p,p)%p;
}

signed main() {
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	n=read();g=read();
	
	if(g==mod) {
		cout<<0<<endl;
		return 0;
	} 
	
	int nn=sqrt(n);
	for(int j=1;j<=4;j++) {
		jc[0]=1;
		for(int i=1;i<=b[4]+1;i++) {
			jc[i]=jc[i-1]*i%b[j];
		}
		for(int i=1;i<=nn;i++) {
			if(n%i==0) {
				a[j]+=c(n,i,b[j]);
				a[j]+=c(n,n/i,b[j]);
			}
		}
	}
	
	for(int i=1;i<=4;i++) {
		m[i]=(mod-1)/b[i];
	}
	int ans=0;
	for(int i=1;i<=4;i++) {
		ans+=a[i]*m[i]%(mod-1)*inv(m[i],b[i])%(mod-1);
	}
	ans%=(mod-1);
	
	cout<<qpow(g,ans)%mod<<endl;

	//fclose(stdin);
	//fclose(stdout);
	return 0;
}

posted @ 2020-07-29 17:25  huayucaiji  阅读(96)  评论(0)    收藏  举报