P2480 [SDOI2010]古代猪文

淦,为什么题面这么复杂啊
一句话题意:
给定整数(q,n(1leq q,n leq 10^9)),求出(q^{sum_{d|n} C_n^d}(mod 999911659))
根据欧拉定理的推论
(a,p)互质时(a^b=a^{b\% varphi(p)}(mod p))
可知

[q^{sum_{d|n} C_n^d\%999911658}(mod 999911659) ]

现在我们只需要求解出(sum_{d|n}C_n^d\%999911658)即可
我们尝试分解质因数,发现(99911658=2*3*4679*35617),它的所有质因子的指数都是(1)
所有我们可以枚举(n)的约数(d),然后用卢卡斯定理

[C_n^d=C_{n\%p}^{d\%p}C_{n/p}^{d/p}(mod p) ]

(C_n^d),分别计算出(sum_{d|n}C_n^d)(2,3,4679,35617)这四个质数取模的结果分别记为(a_1,a_2,a_3,a_4)
可以得出线性同余方程组

[egin{cases}xmod 2=a_1\xmod 3=a_2\x mod 4679=a_3\ xmod35617=a_4end{cases}]

如果看着不习惯可以自己改一下格式,qwq
利用中国剩余定理就诶出最小非负整数解(x),然后利用快速幂求出(q^x)即为答案

/*
@ author:pyyyyyy
-----思路------

-----debug-------
n,q输入的时候反了 
*/
#include<vector>
#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int mod=999911658;//这个模数是已经用过欧拉定理的推论的 
const int N=50111;
int q,n;
int jc[N];
int a[5],b[5]={0,2,3,4679,35617};
void init(int p)
{
	jc[0]=1;
	for(int i=1;i<=p;++i) jc[i]=(jc[i-1]%p*i)%p;
}
int ksm(int a,int b,int p)
{
	int ret=1;
	while(b)
	{
		if(b&1) ret=(ret*a)%p;
		a=(a*a)%p;
		b>>=1;
	}
	return ret%p;
}
int exgcd(int a,int b,int &x,int &y)
{
	if(b==0) {
		x=1;y=0;return a;
	}
	int d=exgcd(b,a%b,x,y);
	int z=x;x=y;y=z-y*(a/b);
	return d; 
}

int C(int n,int m,int p)
{
	if(n<m) return 0;
	return (jc[n]%p*ksm(jc[m],p-2,p)%p*ksm(jc[n-m],p-2,p)%p)%p;
}
int lucas(int n,int m,int p)
{
	if(n<m) return 0;
	if(!n) return 1;
	return lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}
int M[5];
int crt()
{
	int ans=0;
	int m=1;
	for(int i=1;i<=4;++i) m*=b[i];
	for(int i=1;i<=4;++i) M[i]=m/b[i];
	for(int i=1;i<=4;++i)
	{
		int x,y,d;
		d=exgcd(M[i],b[i],x,y);
		x=(x%b[i]+b[i])%b[i];
		ans+=(a[i]%mod*M[i]%mod*x%mod)%mod;
	}
	return ans%mod;
	
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	cin>>q>>n;
	cin>>n>>q;
	if(q%(mod+1)==0)
	{
	 	cout<<0;
	 	return 0;
	} 
	for(int k=1;k<=4;++k)//分别对应a_k
	{
		init(b[k]);//预处理出来当前模数下的阶乘
		//枚举d|n
//		for(int i=1;i<=10;++i) cout<<jc[i]<<' ';
//		cout<<endl;
		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];
//				if(i!=sqrt(n)) a[k]+=(lucas(n,i,b[k])%b[k]+lucas(n,n/i,b[k])%b[k])%b[k];
//				else if(i==sqrt(n)) a[k]+=lucas(n,i,b[k])%b[k];
//				cout<<a[k]<<'
';
			}	
		} 
	}
//	for(int i=1;i<=4;++i) cout<<a[i]<<' ';
	int x=crt();
//	int x=0;
//	for(int i=1;i<=4;i++)
//        x=(x+a[i]*(mod/b[i])%mod*ksm(mod/b[i],b[i]-2,b[i]))%mod;
	cout<<ksm(q,x,mod+1);
	return 0;
}
原文地址:https://www.cnblogs.com/pyyyyyy/p/12742540.html