组合数comb
递推法
时间复杂度:O(n*m)
不取模版本
const int N = 60;//N最大为60,否则会爆long long,当初始化需要N,直接给数组开N+10,N取准确值
ll f[N+10][N+10];
void init() {
for (int i = 0; i <= N; i++) {
for (int j = 0; j <= i; j++) {
if (!j) {
f[i][j] = 1;
continue;
}
f[i][j] = f[i - 1][j - 1] + f[i - 1][j];
}
}
}
公式法
时间复杂度:O(n)
[公式]
\[\begin{gathered}
\mathrm{C}_n^m=\frac{\mathrm{A}_n^m}{\mathrm{A}_m^m}=\frac{n(n-1)(n-2)\cdots(n-m+1)}{m!} =\frac{n!}{m!(n-m)!},\quad n,m\in\mathbb{N}^*,\text{并且}m\leq n \\
\mathrm{C}_n^0=\mathrm{C}_n^n =1
\end{gathered}
\]
const int N = 2000000;
const int mod = 1e9 + 7;
ll inv_fac[N+10], fac[N+10];
ll qmi(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
void init() {
fac[0] = 1;
for (int i = 1; i <= N; i++) {
fac[i] = fac[i - 1] * i % mod;
}
inv_fac[N] = qmi(fac[N], mod - 2);
for (int i = N; i >= 1; i--) {
inv_fac[i - 1] = inv_fac[i] * i % mod;
}
}
ll comb(int n, int k) {
return fac[n] * inv_fac[k] % mod * inv_fac[n - k] % mod;
}