Lucas 定理
int fc[200010], inv[200010];
int C(int n, int m, int p){
if (m < n)return 0;
if (n >= p || m >= p)return 1ll * C(n / p, m / p, p) * C(n % p, m % p, p) % p;
return 1ll * fc[m] * inv[n] % p * inv[m - n] % p;
}
int fp(int a, int b, int p){
int ret = 1;
for (; b; b >>= 1, a = 1ll * a * a % p)
if (b & 1)ret = 1ll * ret * a % p;
return ret;
}
//预处理
fc[0] = 1;for (int i = 1; i < p; ++i)fc[i] = 1ll * fc[i - 1] * i % p;
inv[p - 1] = fp(fc[p - 1], p - 2, p);for (int i = p - 2; i >= 0; --i)inv[i] = 1ll * inv[i + 1] * (i + 1) % p;
扩展 Lucas
模板:P4720 【模板】扩展卢卡斯定理/exLucas
#include <bits/stdc++.h>
#define int long long
using namespace std;
int mul(int a, int b, int M){return __int128(a) * b % M;}
int mulc(int M, int a, int b, int c){return mul(mul(a, b, M), c, M);}
int fpw(int a, int b){int ret = 1;for (; b; b >>= 1, a *= a)if (b & 1)ret *= a;return ret;}
int fpw(int a, int b, int m){int ret = 1;for (; b; b >>= 1, a = mul(a, a, m))if (b & 1)ret = mul(ret, a, m);return ret;}
int fct(int n, int p, int M){//n!/p^x mod M
vector<int> f(p); f[0] = 1;
for (int i = 1; i < p; ++i)f[i] = f[i - 1] * i % M;
int res = 1, tg = 0;
while (n > 1){tg ^= (n / p) & 1;res = res * f[n % p] % M;n /= p;}
if (tg)res = M - res;return res;
}
int G(int n, int p){return n < p? 0 : G(n / p, p) + n / p;}
void exgcd(int a, int b, int &x, int &y){
if (!b)return x = 1, y = 0, (void)0;
exgcd(b, a % b, x, y); y = x - a / b * (x = y);
}
int inv(int a, int p){int x, y;exgcd(a, p, x, y);return (x + p) % p;}
pair<int, int> C(int n, int m, int a, int r){//C(n,m)%a^r, a^r
int p = fpw(a, r);
int N = fct(n, a, p), M = fct(m, a, p), Nm = fct(n - m, a, p);
return {mulc(p, fpw(a, G(n, a) - G(m, a) - G(n - m, a), p), N, inv(M * Nm % p, p)), p};
}
int crt(vector<pair<int, int> > ve, int n){
int ans = 0;
for (int i = 0; i < ve.size(); ++i){
auto [a, r] = ve[i];int m = n / r, b, y;
exgcd(m, r, b, y);ans = (ans + a * m * b % n) % n;
}
return (ans % n + n) % n;
}
signed main(){
int n, m, p, t;
cin >> n >> m >> p, t = p;
vector<pair<int, int> > fc;
for (int i = 2; i * i <= p; ++i)
if (p % i == 0){
int cnt = 0;while (p % i == 0)p /= i, ++cnt;
fc.emplace_back(i, cnt);
}
if (p > 1)fc.emplace_back(p, 1);
vector<pair<int, int> > crtv;
for (auto [a, r] : fc)
crtv.emplace_back(C(n, m, a, r));
cout << crt(crtv, t) << endl;
return 0;
}
参考
- \(\text{12.11 math1.pdf \; \;by Tx\_Lcy}\)