组合数

// 非正常模数
const int N = 5005;
const int mod = 998244353;
int C[N][N];
void C_init() {
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 - 1] + C[i - 1][j]) % mod;
}
}
}
// 模素数意义下
const int N = 1e5 + 5;
struct Comb {
vector<Z> fac;
vector<Z> invfac;
vector<Z> inv;
Comb() : fac{1}, invfac{1}, inv{0} {}
Comb(int n) : Comb() {
fac.resize(n + 1);
invfac.resize(n + 1);
inv.resize(n + 1);
for (int i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * i;
}
invfac[n] = fac[n].inv();
for (int i = n; i > 0; i--) {
invfac[i - 1] = invfac[i] * i;
inv[i] = invfac[i] * fac[i - 1];
}
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac[n] * invfac[m] * invfac[n - m];
}
} comb(N);