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;
}
posted @ 2025-08-02 16:19  David9006  阅读(16)  评论(0)    收藏  举报