[SDOI2010]古代猪文

[SDOI2010]古代猪文
一道数学题。
题解回去补
flag++

#include <cstdio>
#include <cmath>
long long n,g;
long long prime[4]= {2,3,4679,35617};
const long long mod=999911659;
int x[4];
long long fac[55555],inv[55555];
long long lucas(long long N,long long M,long long P) {
	if(N<M){return 0;}
	if(N<P&&M<P) {return fac[N]*inv[M]%P*inv[N-M]%P;}
	return lucas(N%P,M%P,P)*lucas(N/P,M/P,P)%P;
}
long long work(long long p) {
	fac[0]=1;
	long long ans=0;
	for(int i=1; i<p; i++) fac[i]=fac[i-1]*i%p;
    inv[p-1]=p-1;
    for(int i=p-2;~i;i--) inv[i]=inv[i+1]*(i+1)%p;
	long long lim=sqrt(n);
	for(int i=1; i<=lim; i++) {
		if(n%i) continue;
		ans=(ans+lucas(n,i,p))%p;
		if(n/i==i)continue;
		ans=(ans+lucas(n,n/i,p))%p;
	}
	return ans;
}
int exgcd(int a,int b,long long &x,long long &y) {
	if(!b) {
		x=1,y=0;
		return a;
	}
	int ans=exgcd(b,a%b,x,y),t=x;
	x=y,y=t-a/b*y;
	return ans;
}
long long ksm(long long d,int z) {
	long long res=1;
	while(z) {
		if(z&1) res=res*d%mod;
		d=d*d%mod;
		z>>=1;
	}
	return res;
}
void China() {
	long long ans=0,xx,y;
	for(int i=0; i<4; i++) {
		long long t=(mod-1)/prime[i];
		exgcd(prime[i],t,xx,y);
		ans=(ans+y*t*x[i])%(mod-1);
		if(ans<0) ans+=(mod-1);
	}
	printf("%lld",ksm(g,ans));
}
int main() {
	scanf("%d%d",&n,&g);
	if(g%mod==0) {
		putchar('0');
		return 0;
	}
	for(int i=0;i<4;i++)
	x[i]=work(prime[i]);
	China();
	return 0;
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9252624.html