组合数模版集合
组合数模版
一、组合数逆元求模
\((组合数不超过1e7且模数为质数且组合数不超过模数)\)
struct C_fi{
inline i64 qp(i64 a, i64 b, i64 p = 1e9 + 7) {
i64 res = 1;
for (; b; b >>= 1LL, a = 1LL * a * a % p) {
if (b & 1) res = 1LL * res * a % p;
}
return res;
}
inline i64 get_inv(i64 a, i64 p = 1e9 + 7) { return qp(a, p - 2, p); }
int N;
vector<i64> fac, inv;
C_fi() {}
C_fi(int N_, i64 p = 1e9 + 7) : fac(N_ + 1), inv(N_ + 1) {
N = N_;
fac[0] = 1;
inv[0] = 1;
for (i64 i = 1; i <= N; i++) fac[i] = 1LL * fac[i - 1] * i % p;
inv[N] = get_inv(fac[N], p);
for (i64 i = N - 1; i >= 1; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % p;
}
inline i64 C(int n, int m, i64 p = 1e9 + 7) { return fac[n] * inv[n - m] % p * inv[m] % p; }
};
二、\(dp\) 求模
\((组合数在2e3-1e4之间可用)\)
struct dp_C{
static const int N = 3000;
i64 c[N + 1][N + 1];
dp_C(i64 p = 1e9 + 7) {
for (int i = 0; i <= N; i++) {
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; j++) {
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % p;
}
}
}
// 以下可写也可不写
inline i64 qp(i64 a, i64 b, i64 p = 1e9 + 7) {
i64 res = 1;
for (; b; b >>= 1LL, a = a * a % p) {
if (b & 1) res = res * a % p;
}
return res;
}
inline i64 get_inv(i64 a, i64 p = 1e9 + 7) { return qp(a, p - 2, p); }
};
三、\(Lucas\) 取模
\((针对于模数为素数, 组合数大小可以无限, 不过一般看来如果真要用它, 素数需要不超过1e7, 算是比较极限的了)\)
struct Lucas{
inline i64 qp(i64 a, i64 b, i64 p = 100007) {
i64 res = 1;
for (; b; b >>= 1LL, a = a * a % p) {
if (b & 1) res = res * a % p;
}
return res;
}
inline i64 get_inv(i64 a, i64 p = 100007) { return qp(a, p - 2, p); }
int N;
vector<i64> fac;
Lucas() {}
Lucas(int N_, i64 p = 100007) : fac(N_ + 1) {
N = N_;
fac[0] = 1;
for (i64 i = 1; i <= N; i++) fac[i] = fac[i - 1] * i % p;
}
inline i64 C(int n, int m, i64 p = 100007) {
if (m > n) {
return 0LL;
}
return fac[n] * qp(fac[m], p - 2, p) % p * qp(fac[n - m], p - 2, p) % p;
}
inline i64 lucas(i64 n, i64 m, i64 p = 100007) {
if (!m) return 1LL;
return lucas(n / p, m / p, p) * C(n % p, m % p, p) % p;
}
};

浙公网安备 33010602011771号