CF1999F 题解
我们发现,当选择的 \(0\) 的个数小于 \(1\) 的个数时,中位数为 \(1\),否则为 \(0\)。
我们设共有 \(c_0\) 个 \(0\),\(c_1\) 个 \(1\)。
我们考虑当我们选 \(i\)(\(0 \le i \le \dfrac{k - 1}{2}\))个 \(0\) 时的答案:此时有 \(\dbinom{c_0}{i}\) 种选 \(0\) 的方案,和 \(\dbinom{c_1}{k - i}\) 种选 \(1\) 的方案,所以共有 \(\dbinom{c_0}{i} \dbinom{c_1}{k - i}\) 种方案,故此时答案为 \(\dbinom{c_0}{i} \dbinom{c_1}{k - i}\)。
对上式从 \(i = 0\) 到 \(i = \dfrac{k - 1}{2}\) 求和,则最终的答案为 \(\displaystyle \sum_{i = 0}^{(k - 1) / 2} \dbinom{c_0}{i} \dbinom{c_1}{k - i}\)。
先 \(O(n)\) 预处理阶乘与其逆元,再 \(O(k)\) 计算答案即可。
#include <iostream>
using namespace std;
using i64 = long long;
constexpr int MOD = 1e9 + 7, N = 2e5;
inline int mul(int x, int y)
{
return (i64)x * y % MOD;
}
inline int mul(int x, int y, int z)
{
return mul(x, mul(y, z));
}
int fact[N + 5], ifact[N + 5], inv[N + 5];
void prep()
{
fact[0] = fact[1] = ifact[0] = ifact[1] = inv[1] = 1;
for (int i = 2; i <= N; ++i) {
fact[i] = mul(fact[i - 1], i);
inv[i] = mul(MOD - MOD / i, inv[MOD % i]);
ifact[i] = mul(ifact[i - 1], inv[i]);
}
}
inline int C(int n, int m)
{
return m > n ? 0 : mul(fact[n], ifact[m], ifact[n - m]);
}
inline int add(int x, int y)
{
return (x + y) % MOD;
}
void solve_test()
{
int n, k, ans = 0;
int cnt[2] = { 0, 0 };
cin >> n >> k;
while (n-- > 0) {
int x;
cin >> x;
++cnt[x];
}
for (int i = 0; i <= k >> 1; ++i)
ans = add(ans, mul(C(cnt[0], i), C(cnt[1], k - i)));
cout << ans << '\n';
}
int main()
{
prep();
int t;
cin >> t;
while (t-- > 0)
solve_test();
return 0;
}

浙公网安备 33010602011771号