古代猪文[BZOJ1951]\[Sdoi2010]

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

题目描述

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

思路

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

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

否则,因为 999911659 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)  qdnCndqdnCndmod999911658(mod999911659)

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

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

我们可以枚举 n n n的约数 d d d,然后运用Lucas定理,求组合数 C n d C_n^d Cnd,分别计算出 ∑ d ∣ n C n d \sum_{d\mid n}C^d_n dnCnd 2 , 3 , 4679 , 35617 2,3,4679,35617 2,3,4679,35617四个质数取模的结果,记为 a 1 , a 2 , a 3 , a 4 a_1,a_2,a_3,a_4 a1,a2,a3,a4。计算过程中,对于一个质数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} xmod2=a1xmod3=a2xmod4679=a3xmod35671=a4

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

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;	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值