@wsndy-xx
2018-06-19T14:50:01.000000Z
字数 1277
阅读 763
题解
求
由费马小定理
先求质数部分, 记
得同余方程组
定理求
合并
求
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 999911659, MOD = 999911658;
int n, g, num[4], prime[4] = {2, 3, 4679, 35617}, fact[40000] = {1};
int qpow(ll a, int b, int p) {
int ans = 1;
for (; b; a = a * a % p, b >>= 1) {
if (b & 1) {
ans = ans * a % p;
}
}
return ans;
}
int C(int n, int m, int p) {
if (n < m) return 0;
return fact[n] * qpow(fact[n - m] * fact[m], p - 2, p) % p;
}
int lucas(int n, int m, int p) {
if (m == 0) return 1;
return C(n % p, m % p, p) * lucas(n / p, m / p, p) % p;
}
int crt() {
int ans = 0;
for (int i = 0; i < 4; i++) {
int tmp = MOD / prime[i];
ans = (ans + 1LL * num[i] * tmp % MOD * qpow(tmp, prime[i] - 2, prime[i]) % MOD) % MOD;
}
return ans;
}
int main() {
scanf("%d %d", &n, &g);
if (g == mod) {
printf("0\n");
return 0;
}
for (int i = 0; i < 4; i++) {
fact[0] = 1;
for (int j = 1; j <= prime[i]; j++) {
fact[j] = fact[j - 1] * j % prime[i];
}
for (int d = 1; d * d <= n; d++) {
if (n % d != 0) continue;
num[i] = (num[i] + lucas(n, d, prime[i])) % prime[i];
if (n / d == d) continue;
num[i] = (num[i] + lucas(n, n / d, prime[i])) % prime[i];
}
}
printf("%d\n", qpow(g, crt(), mod));
return 0;
}