看到题目和题面想笑……不多说了,进入正题。
题意:求
G∑d|NCdNmod999911659
的值。
首先,可以根据费马小定理得出,原式和
G(∑d|NCdN)mod999911658
在模999911659意义下是同余的。
而只要求得了(∑d|NCdN)mod999911658的值就很容易了。
首先将999911658分解质因数,得999911658=2∗3∗4679∗35617。
而对于(∑d|NCdN)mod2,(∑d|NCdN)mod3,(∑d|NCdN)mod4679和(∑d|NCdN)mod35617,虽然N很大,但是可以发现模数较小,所以可以使用Lucas定理求解这
求得这4个结果后,就可以用中国剩余定理合并了。
注意特判
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll LPF = 999911659, PYZ = LPF - 1, N = 1e5 + 5;
ll n, G, ex[N], num[] = {0, 2, 3, 4679, 35617}, f[N], Inv[N];
ll qpow(ll a, ll b, ll pyz) {
if (a == 0) return 0;
if (a % pyz == 0) return b == 0;
ll res = 1;
while (b) {
if (b & 1) res = res * a % pyz;
a = a * a % pyz;
b >>= 1;
}
return res;
}
void exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) return (void) (x = 1, y = 0);
exgcd(b, a % b, y, x); y -= a / b * x;
}
ll inv(ll a, ll pyz) {
ll x, y; exgcd(a, pyz, x, y);
x = (x % pyz + pyz) % pyz;
return x;
}
ll crt(ll pyz) {
int i; ll ans = 0; for (i = 1; i <= 4; i++)
(ans += ex[i] * (pyz / num[i]) % pyz *
inv(pyz / num[i], num[i]) % pyz) %= pyz;
return ans;
}
ll Lucas(ll n, ll m, ll pyz) {
if (n < m) return 0;
if (n < pyz && m < pyz) return f[n] * Inv[m] % pyz * Inv[n - m] % pyz;
return Lucas(n / pyz, m / pyz, pyz) * Lucas(n % pyz, m % pyz, pyz) % pyz;
}
ll solve(ll lpf) {
int i; f[0] = 1;
for (i = 1; i < lpf; i++) f[i] = f[i - 1] * i % lpf;
Inv[lpf - 1] = lpf - 1; for (i = lpf - 2; i >= 0; i--)
Inv[i] = Inv[i + 1] * (i + 1) % lpf;
ll S = sqrt(n), ans = 0;
for (i = 1; i <= S; i++) if (n % i == 0) {
(ans += Lucas(n, i, lpf)) %= lpf;
if (i != n / i) (ans += Lucas(n, n / i, lpf)) %= lpf;
}
return ans;
}
int main() {
int i; cin >> n >> G; if (G % LPF == 0) return puts("0"), 0;
for (i = 1; i <= 4; i++) ex[i] = solve(num[i]);
cout << qpow(G, crt(PYZ), LPF) << endl;
return 0;
}