题目描述
题意简述:给定
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
Gd∣n∑Cndmod 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) ab≡ab mod ϕ(p)(mod p)
将模数转移到指数上,变为求
∑
d
∣
n
C
n
d
mod
999911658
\sum\limits_{d|n}C_n^d\ \text{mod}\ 999911658
d∣n∑Cnd mod 999911658,然后用快速幂就得到答案了。
然后这东西看着可以用Lucas定理搞,但显然999911658不是质数,用扩展Lucas的方法,将其进行质因数分解,发现
999911658
=
2
∗
3
∗
4679
∗
35617
999911658=2*3*4679*35617
999911658=2∗3∗4679∗35617,于是可以用Lucas分别求
∑
d
∣
n
C
n
d
\sum\limits_{d|n}C_n^d
d∣n∑Cnd模其质因数,设得到的结果为
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}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x≡a1 (mod 2)x≡a2 (mod 3)x≡a3 (mod 4679)x≡a4 (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
<
ϕ
(
p
)
0\le r<\phi(p)
0≤r<ϕ(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)
ab≡an∗ϕ(p)+r≡(aϕ(p))n∗ar≡ar≡ab 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;
}