1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| #include <cstdio>
typedef long long ll; const int N = 100000; int p, cnt, pri[N], k[N], cpoy_p; ll n, m;
inline ll qpow(ll base, ll exp, const int &mod) { ll res = 1; while (exp) { if (exp & 1) res = res * base % mod; base = base * base % mod; exp >>= 1; } return res; }
void exgcd(ll a, ll b, ll &x, ll &y) { if (b == 0) return x = 1, y = 0, void(); exgcd(b, a % b, y, x); y -= a / b * x; }
namespace CRT {
int a[N], ans = 0, pk; ll inv, y;
inline int solve() { for (int i = 1; i <= cnt; ++i) { pk = qpow(pri[i], k[i], p + 1); exgcd(p / pk, pk, inv, y); ans += a[i] * inv % p * (p / pk) % p; if (ans >= p) ans -= p; if (ans < 0) ans += p; } return ans; }
}
namespace Exlucas {
int prime, mod; ll h;
inline void MOD(ll &x, const int &mod) { if (x >= mod) x %= mod; }
ll f(ll n) { if (n == 0) return 1; h += n / prime; ll res = 1, tmp = 1; res *= f(n / prime); MOD(res, mod); for (int i = 1; i <= mod; ++i) { if (i % prime) (tmp *= i) %= mod; } res *= qpow(tmp, n / mod, mod); MOD(res, mod); for (ll i = n / mod * mod; i <= n; ++i) { if (i % prime) { res *= i % mod; MOD(res, mod); } } return res; }
inline ll solve(int i) { prime = pri[i], mod = qpow(prime, k[i], p + 1); int exp = 0; ll res = 1, inv, y; h = 0, res *= f(n), exp += h;
h = 0, exgcd(f(m), mod, inv, y); inv = (inv % mod + mod) % mod; res *= inv; MOD(res, mod); exp -= h;
h = 0, exgcd(f(n - m), mod, inv, y); inv = (inv % mod + mod) % mod; res *= inv; MOD(res, mod); exp -= h;
return res * qpow(prime, exp, mod) % mod; }
}
signed main() { #ifndef ONLINE_JUDGE #ifdef LOCAL freopen("testdata.in", "r", stdin); freopen("testdata.out", "w", stdout); #else freopen("ExLucas.in", "r", stdin); freopen("ExLucas.out", "w", stdout); #endif #endif
scanf("%lld%lld%d", &n, &m, &p); cpoy_p = p; for (int i = 2; i * i <= p; ++i) { if (cpoy_p % i == 0) { pri[++cnt] = i; while (cpoy_p % i == 0) { cpoy_p /= i, k[cnt]++; } } } if (cpoy_p != 1) pri[++cnt] = cpoy_p, k[cnt] = 1; for (int i = 1; i <= cnt; ++i) { CRT::a[i] = Exlucas::solve(i); } printf("%d", CRT::solve()); return 0; }
|