古代猪文[BZOJ1951]\[Sdoi2010]

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89636628

欢迎大家访问我的老师的OJ———caioj.cn

题目描述

传送门
(“在那山的那边海的那边有一群小肥猪。他们活泼又聪明,他们调皮又灵敏。他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心……” )xswl

思路

一句话题意:给定整数 q , n ( 1 q , n 1 0 9 ) q,n(1\le q,n\le 10^9) ,计算 q d n C n d ( mod 999911659 ) . q^{\sum_{d\mid n}C_n^d}(\operatorname{mod} 999911659).

首先先拿部分分, q = 999911659 q=999911659 时,直接输出" 0 0 ".

否则,因为 999911659 999911659 是质数,所以q,n互质。由欧拉定理的推论得:
  q d n C n d q d n C n d mod 999911658 ( mod 999911659 ) \large\ q^{\sum_{d\mid n}C_n^d}\equiv q^{\sum_{d\mid n}C_n^d\operatorname{mod}999911658}(\operatorname{mod} 999911659)

因此我们只要求出 d n C n d mod 999911658 \sum_{d\mid n}C_n^d\operatorname{mod}999911658 即可。

999911658 999911658 分解质因数,得到: 999911658 = 2 x 3 x 4679 x 35617 999911658=2\operatorname{x}3\operatorname{x}4679\operatorname{x}35617

我们可以枚举 n n 的约数 d d ,然后运用Lucas定理,求组合数 C n d C_n^d ,分别计算出 d n C n d \sum_{d\mid n}C^d_n 2 , 3 , 4679 , 35617 2,3,4679,35617 四个质数取模的结果,记为 a 1 , a 2 , a 3 , a 4 a_1,a_2,a_3,a_4 。计算过程中,对于一个质数p,可以预处理p以内的所有阶乘以及阶乘的模p乘法逆元,从而快速计算组合数。

最后,用中国剩余定理求解线性同余方程组:
{ x mod 2 = a 1 x mod 3 = a 2 x mod 4679 = a 3 x mod 35671 = a 4 \begin{cases}x\operatorname{mod}2=a_1\\x\operatorname{mod} 3=a_2\\x\operatorname{mod}4679=a_3\\x\operatorname{mod}35671=a_4\end{cases}

得到 d n C n d mod 999911658 \sum_{d\mid n}C_n^d\operatorname{mod}999911658 的最小非负整数解 x x 。再用快速幂求 q x q^x 即可。

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define ll long long
#define gc getchar()
using namespace std;
const ll P=999911659;
ll p[5]={0,2,3,4679,35617},m[5],t[5];
ll pn[5][35617][2]={{},{{1,1},{1,1}},{{1,1},{1,1},{2,2}},{{1,1},{1,1}},{{1,1},{1,1}}};
inline void qr(ll &x)
{
	x=0;ll f=1;char c=gc;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
	x*=f;
}
void qw(ll x)
{
	if(x/10)qw(x/10);
	putchar(x%10+48);
}
inline ll pow_mod(ll a,ll b,ll c)
{
	ll ans=1;a%=c;
	b%=(c-1);//费马小定理
	while(b)
	{
		if(b&1)ans=ans*a%c;
		b>>=1;a=a*a%c;
	}
	return ans;
}
inline ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(!b){x=1;y=0;return a;}
	ll tx,ty;ll d=exgcd(b,a%b,tx,ty);
	x=ty;y=tx-(a/b)*ty;
	return d;
}
ll C(ll d,ll n,ll i)//Lucas
{
	if(d<p[i]&&n<p[i])
		return pn[i][n][0]*pn[i][d][1]*pn[i][n-d][1]%p[i];
	return C(d%p[i],n%p[i],i)*C(d/p[i],n/p[i],i);
}
inline void pre()
{
	for(int i=2;i<p[3];i++)
	{
		pn[3][i][0]=pn[3][i-1][0]*i%p[3];
		pn[3][i][1]=pow_mod(pn[3][i][0],p[3]-2,p[3]);
	}
	for(int i=2;i<p[4];i++)
	{
		pn[4][i][0]=pn[4][i-1][0]*i%p[4];
		pn[4][i][1]=pow_mod(pn[4][i][0],p[4]-2,p[4]);
	}
	for(int i=1;i<=4;i++)
	{
		m[i]=(P-1)/p[i];
		ll x,y;exgcd(m[i],p[i],x,y);
		t[i]=x;
	}
}
int main()
{
	ll n,q;qr(n),qr(q);
	q%=P;
	if(!q){puts("0");return 0;}
	pre();
	ll a[5]={0,0,0,0,0};
	for(ll d=1;d*d<=n;d++)
		if(n%d==0)
		{
			for(int i=1;i<=4;i++)
			{
				a[i]=(a[i]+C(d,n,i))%p[i];
				if(d*d!=n)a[i]=(a[i]+C(n/d,n,i))%p[i];
			}
		}
	ll ans=0;
	for(int i=1;i<=4;i++)
		ans=(a[i]*m[i]%(P-1)*t[i]%(P-1)+ans)%(P-1);
	ans=(ans+(P-1))%(P-1);
	qw(pow_mod(q,ans,P));puts("");
	return 0;	
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89636628
今日推荐