组合数
// 非正常模数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);