ABC266 G(二项式反演)
题目链接
题目大意:有\(a\)个\(R,\ b个G,\ c个B\),要求出来恰好有\(k\)个连续的\(RG\)的排列方案数。
思路:
可以先将问题转化成至少有\(k\)个\(RG\)的排列方案数有多少,然后可以用二项式反演的方法,将所有\(cnt_{RG} = k\)的方案数加起来就好了。二项式反演有这样的式子\(F(n) = \sum \binom{n}{i} D(i) \Rightarrow D(n) = \sum (-1) ^ {n - i} \binom{n}{i} F(i)\),那么我们将\(D(n)\)求出来就好了。
int r, g, b, k;
std::cin >> r >> g >> b >> k;
int n = r + g + b;
fac[0] = fav[0] = 1;
for (int i = 1; i <= n; i++) fac[i] = 1LL * fac[i - 1] * i % mod;
fav[n] = power(fac[n], mod - 2);
for (int i = n - 1; i >= 1; i--) fav[i] = 1LL * fav[i + 1] * (i + 1) % mod;
auto C = [&](int n, int m) -> int {
if (m > n || m < 0) return 0;
return 1ll * fac[n] * fav[m] % mod * fav[n - m] % mod;
};
std::vector<int> f(n + 1);
for (int i = 0; i <= std::min(r, g); i++) {
int x = r - i, y = g - i;
int m = x + y + i + b;
f[i] = 1ll * C(m, i) * C(m - i, x) % mod * C(m - x - i, y) % mod * C(m - x - i - y, b) % mod;
}
int ans = 0;
for (int i = k; i <= std::min(r, g); i++) {
int p = ((i - k) & 1) ? -1 : 1;
ans = (1ll * ans + mod + 1ll * p * C(i, k) % mod * f[i] % mod) % mod;
}
std::cout << ans << "\n";

浙公网安备 33010602011771号