古代猪文
题目链接:ybt高效进阶6-4-3 / luogu P2480
题目大意
给你 n,g,然后 p=∑i|n C(n,i)。
然后要你求 g^p 模 999911659 的值。
思路
首先如果求出了 p p p 就是一个快速幂。
然后发现
p
p
p 不能取模,那我们考虑用(扩展)欧拉定理。
如果
g
g
g 跟
999911659
999911659
999911659 不互质,那因为
999911659
999911659
999911659 是质数,就一定有
999911659
∣
g
999911659|g
999911659∣g,所以结果肯定是
0
0
0。
如果互质,那就有
g
p
≡
g
p
m
o
d
φ
(
999911659
)
(
m
o
d
999911659
)
g^p\equiv g^{p\bmod\varphi(999911659)}(\bmod\ 999911659)
gp≡gpmodφ(999911659)(mod 999911659),那
999911659
999911659
999911659 是质数,所以就是:
g
p
≡
g
p
m
o
d
999911658
(
m
o
d
999911659
)
g^p\equiv g^{p\bmod999911658}(\bmod\ 999911659)
gp≡gpmod999911658(mod 999911659)
那接着就要求
p
m
o
d
999911658
p\bmod999911658
pmod999911658,对于因数我们可以直接暴力枚举,然后你发现模数不是质数不能用逆元求组合数。
那你把模数质因数分解一下,可以分成四个不同的质数:
2
,
3
,
4679
,
35617
2,3,4679,35617
2,3,4679,35617。
然后我们可以分别求这个四个数的结果(用 Lucas 定理),然后由于四个互相互质且不同,我们可以直接 EXCRT 合并起来。(好吧直接 CRT 都行,但我写了 EXCRT)
然后就可以了。
代码
#include<cstdio>
#define ll long long
#define mo 999911658
#define mod 999911659
using namespace std;
ll n, g, p[5] = {0, 2, 3, 4679, 35617};
ll a[5];
ll ksm(ll x, ll y, ll p) {
ll re = 1;
x %= p;
while (y) {
if (y & 1) re = (re * x) % p;
x = (x * x) % p;
y >>= 1;
}
return re;
}
ll inv(ll x, ll p) {
return ksm(x, p - 2, p);
}
ll C(ll n, ll m, ll p) {
if (n > m) return 0;
ll re = 1, div = 1;
for (int i = n + 1; i <= m; i++)
re = (re * i) % p;
for (int i = 1; i <= m - n; i++)
div = (div * i) % p;
return re * inv(div, p) % p;
}
ll Lucas(ll n, ll m, ll p) {
if (!n) return 1;
return Lucas(n / p, m / p, p) * C(n % p, m % p, p) % p;
}
void devide() {
for (ll i = 1; i * i <= n; i++)
if (n % i == 0) {
for (int j = 1; j <= 4; j++)
a[j] = (a[j] + Lucas(i, n, p[j])) % p[j];
if (i * i != n) {
for (int j = 1; j <= 4; j++)
a[j] = (a[j] + Lucas(n / i, n, p[j])) % p[j];
}
}
}
ll work() {
for (int i = 2; i <= 4; i++) {
ll A = (a[i] - a[1]) * inv(p[1], p[i]) % p[i];
ll M = p[1] * p[i];
a[1] = ((a[1] + A * p[1] % M) % M + M) % M;
p[1] = M;
}
return a[1];
}
int main() {
scanf("%lld %lld", &n, &g);
if (g % mod == 0) {
printf("0");
return 0;
}
devide();
printf("%lld", ksm(g, work(), mod));
return 0;
}