「SDOI2010」 古代猪文 - Lucas定理+CRT

题目描述

Luogu2480

题意简述:给定 n , G n,G n,G,求
G ∑ d ∣ n C n d mod  999911659 G^{\sum\limits_{d|n}C_n^d}\text{mod}\ 999911659 GdnCndmod 999911659

分析

G  mod  999911659 = 0 G\ \text{mod}\ 999911659=0 G mod 999911659=0,则答案为 0 0 0。否则,可以发现, 999911659 999911659 999911659是个质数,可以运用欧拉定理的推论:

g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,则 a b ≡ a b  mod  ϕ ( p ) ( mod  p ) a^b\equiv a^{b\ \text{mod}\ \phi(p)}(\text{mod}\ p) abab mod ϕ(p)(mod p)

将模数转移到指数上,变为求 ∑ d ∣ n C n d  mod  999911658 \sum\limits_{d|n}C_n^d\ \text{mod}\ 999911658 dnCnd mod 999911658,然后用快速幂就得到答案了。
然后这东西看着可以用Lucas定理搞,但显然999911658不是质数,用扩展Lucas的方法,将其进行质因数分解,发现 999911658 = 2 ∗ 3 ∗ 4679 ∗ 35617 999911658=2*3*4679*35617 999911658=23467935617,于是可以用Lucas分别求 ∑ d ∣ n C n d \sum\limits_{d|n}C_n^d dnCnd模其质因数,设得到的结果为 a 1 , a 2 , a 3 , a 4 a_1,a_2,a_3,a_4 a1,a2,a3,a4,然后再用中国剩余定理求解一下方程组:
{ x ≡ a 1   ( mod  2 ) x ≡ a 2   ( mod  3 ) x ≡ a 3   ( mod  4679 ) x ≡ a 4   ( mod  35617 ) \begin{cases} x\equiv a_1\ (\text{mod}\ 2)\\ x\equiv a_2\ (\text{mod}\ 3)\\ x\equiv a_3\ (\text{mod}\ 4679)\\ x\equiv a_4\ (\text{mod}\ 35617)\\ \end{cases} xa1 (mod 2)xa2 (mod 3)xa3 (mod 4679)xa4 (mod 35617)

设该方程组的最小正整数解为 x x x,则答案为 G x G^x Gx

附:欧拉定理推论的证明。
b = n ∗ ϕ ( p ) + r b=n*\phi(p)+r b=nϕ(p)+r,其中 0 ≤ r &lt; ϕ ( p ) 0\le r&lt;\phi(p) 0r<ϕ(p),则 r = b  mod  ϕ ( p ) r=b\ \text{mod}\ \phi(p) r=b mod ϕ(p)。由于欧拉定理 a ϕ ( p ) ≡ 1   ( mod  p ) a^{\phi(p)}\equiv1\ (\text{mod}\ p) aϕ(p)1 (mod p),所以 a b ≡ a n ∗ ϕ ( p ) + r ≡ ( a ϕ ( p ) ) n ∗ a r ≡ a r ≡ a b  mod  ϕ ( p )   ( mod  p ) a^b\equiv a^{n*\phi(p)+r}\equiv (a^{\phi(p)})^n*a^r\equiv a^r\equiv a^{b\ \text{mod}\ \phi(p)}\ (\text{mod}\ p) abanϕ(p)+r(aϕ(p))nararab mod ϕ(p) (mod p)

代码

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
const LL P=999911659;
const LL N=100005;
LL fac[N];
LL md[5]={4,2,3,4679,35617};
LL b[5],G,n;
LL ksm(LL x,LL y,LL p) {//快速幂 
	x%=p;LL res=1LL;
	for (;y;y>>=1,x=x*x%p)
		if (y&1) res=res*x%p;
	return res;
}
void initfac(LL n,LL p) {//阶乘预处理 
	fac[0]=1;
	for (int i=1;i<=n;i++)
		fac[i]=fac[i-1]*i%p;
}
LL C(LL n,LL m,LL p) {//计算C(n,m)
	if (m>n) return 0;
	return (fac[n]*ksm(fac[m],p-2,p))%p*ksm(fac[n-m],p-2,p);
}
LL Lucas(LL n,LL m,LL p) {//Lucas定理C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p
	if (!m) return 1;
	return (Lucas(n/p,m/p,p)%p*C(n%p,m%p,p)%p)%p;
}
LL Exgcd(LL a,LL b,LL&x,LL&y) {//扩展欧几里得 
	if (!b) {
		x=1,y=0;
		return a;
	}
	LL d=Exgcd(b,a%b,x,y),t;
	t=x;
	x=y;
	y=t-(a/b)*y;
	return d;
}
LL CRT(LL *a,LL *m,LL n) {//中国剩余定理x==ai(mod mi)
	LL M=1,ans=0;
	for (int i=1;i<=n;i++) M*=m[i];
	for (int i=1;i<=n;i++) {
		LL x,y;
		Exgcd(M/m[i],m[i],x,y);
		x=(x%m[i]+m[i])%m[i];//求逆元 
		ans=(ans+a[i]*x%M*M/m[i])%M;
	}
	return (ans%M+M)%M;
}
LL Solve(LL n,LL p) {
	LL ans=0,m=sqrt(n);
	initfac(N-5,p);
	for (LL i=1;i<=m;i++)//枚举约数 
		if (n%i==0) {
			ans+=Lucas(n,i,p);
			if (i*i!=n) ans+=Lucas(n,n/i,p);//去除重复的一个 
		}
	return ans;
}
int main() {
	scanf("%lld%lld",&n,&G);
	if (G%P!=0) {
		for (int i=1;i<=4;i++)
			b[i]=Solve(n,md[i]);
		printf("%lld",ksm(G,CRT(b,md,4),P));
	} else printf("0");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值