Description \text{Description} Description
给定正整数 n , g n,g n,g,求 g ∑ k ∣ n C n k m o d 999911659 g^{\sum_{k\mid n}C_{n}^{k}}\bmod 999911659 g∑k∣nCnkmod999911659。
- 对于 100 % 100\% 100% 的数据, 1 ≤ n , g ≤ 1 0 9 1\le n,g \le 10^9 1≤n,g≤109。
Solution \text{Solution} Solution
前置芝士:
- 欧拉定理
- L u c a s \rm Lucas Lucas 定理
- C R T \rm CRT CRT
由欧拉定理知 g ∑ k ∣ n C n k ≡ g ( ∑ k ∣ n C n k ) m o d φ ( 999911659 ) ≡ g ( ∑ k ∣ n C n k ) m o d 999911658 ( m o d 999911659 ) g^{\sum_{k\mid n}C_{n}^{k}}\equiv g^{(\sum_{k\mid n}C_{n}^{k})\bmod\ \varphi(999911659)}\equiv g^{(\sum_{k\mid n}C_{n}^{k})\bmod\ 999911658}\pmod{999911659} g∑k∣nCnk≡g(∑k∣nCnk)mod φ(999911659)≡g(∑k∣nCnk)mod 999911658(mod999911659)
指数可以快速幂 O ( log 999911658 ) O(\log 999911658) O(log999911658) 解决,找因数是 Θ ( n ) \Theta(\sqrt{n}) Θ(n) 的。
于是问题转化为求 C n k m o d 999911658 C_{n}^{k}\bmod 999911658 Cnkmod999911658。
直接算是不行的,但是直接 L u c a s \rm Lucas Lucas 因为模数太大也不行。
999911658
=
2
×
3
×
4679
×
35617
999911658=2×3×4679×35617
999911658=2×3×4679×35617,令
x
=
C
n
k
x=C_{n}^{k}
x=Cnk,考虑分别算出
{
x
m
o
d
2
x
m
o
d
3
x
m
o
d
4679
x
m
o
d
35617
\begin{cases} x\bmod 2\\ x\bmod 3\\ x\bmod 4679\\ x\bmod 35617 \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧xmod2xmod3xmod4679xmod35617
这个就可以用
L
u
c
a
s
\rm Lucas
Lucas。
再用 C R T \rm CRT CRT 合并即可。
Code \text{Code} Code
//18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
typedef long long ll;
using namespace std;
const int MAXN = 35620;
const int MOD = 999911659;
int qpow(int a, int b, int p)
{
int base = a, ans = 1;
while (b)
{
if (b & 1)
{
ans = (ll)ans * base % p;
}
base = (ll)base * base % p;
b >>= 1;
}
return ans;
}
int inv(int a, int p)
{
return qpow(a, p - 2, p);
}
int fac[MAXN], inv_fac[MAXN];
void init(int p)
{
fac[0] = 1;
for (int i = 1; i < p; i++)
{
fac[i] = (ll)fac[i - 1] * i % p;
}
inv_fac[p - 1] = inv(fac[p - 1], p);
for (int i = p - 2; i >= 0; i--)
{
inv_fac[i] = (ll)inv_fac[i + 1] * (i + 1) % p;
}
}
int C(int n, int m, int p)
{
if (m > n)
{
return 0;
}
return (ll)fac[n] * inv_fac[n - m] % p * inv_fac[m] % p;
}
int Lucas(int n, int m, int p)
{
if (!m)
{
return 1;
}
return (ll)Lucas(n / p, m / p, p) * C(n % p, m % p, p) % p;
}
const int a[5] = {0, 2, 3, 4679, 35617};
int b[5];
int CRT()
{
int m = MOD - 1, ans = 0;
for (int i = 1; i <= 4; i++)
{
int mi = m / a[i];
int Mi = inv(mi, a[i]);
ans = (ans + (ll)b[i] * mi * Mi) % m;
}
return ans;
}
int main()
{
int n, g;
scanf("%d%d", &n, &g);
if (!(g % MOD))
{
puts("0");
return 0;
}
for (int i = 1; i <= 4; i++)
{
init(a[i]);
for (int j = 1; j * j <= n; j++)
{
if (!(n % j))
{
b[i] = (b[i] + Lucas(n, j, a[i])) % a[i];
if (j * j != n) //注意完全平方数
{
b[i] = (b[i] + Lucas(n, n / j, a[i])) % a[i];
}
}
}
}
printf("%d\n", qpow(g, CRT(), MOD));
return 0;
}