Codeforces Round 964 (Div. 4)

注册了一个新的小号打了一把,大部分时间其实都在 \(in \ queue\)\(G1,G2\) 的三分多了一次重复询问,甚至半个多小时才看出来。搞笑的是我忘了题目是多测,然后就一直提交一直 \(Wrong \ answer \ in \ test \ 1\)。这场的题目整体来说比以前简单很多啊,感觉 \(Specialist\) 应该都能随便 \(AK\) 啊。


感觉 \(F\) 题是唯一比较有意思的题,大概是一点点组合数学吧,代码不难写,有板子的话应该会很快。题目的意思是给一个 \(0\)\(1\) 序列,问这个序列的所有指定长度非连续子序列的中位数的和是多少。数一下 \(0\)\(1\) 的数量,显然当 \(0\) 作为中位数时对答案是没有贡献的,所以中位数一定是 \(1\),然后暴力枚举一下这个 \(1\) 前面有多少个 \(1\) 就可以了。记得特判一下全 \(0\) 序列。

#pragma GCC optimize("unroll-loops, Ofast")
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
#define endl '\n'
#define lowbit(x) x & -x
constexpr i64 Mod = 1000000007;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
i64 n, m, k;

void init() {}

class Z {
    using i64 = long long;
    static const i64 Mod = 1000000007;
public:
    i64 num;
    Z() = default;
    Z(i64 _num) : num((_num % Mod + Mod) % Mod) {}
    i64 val() const {
        return num;
    }
    Z &operator = (i64 b) {
        return *this = Z(b);
    }
    friend bool operator < (Z a, Z b) {
        return a.num < b.num;
    }
    friend bool operator >(Z a, Z b) {
        return a.num > b.num;
    }
    friend bool operator <=(Z a, Z b) {
        return a.num <= b.num;
    }
    friend bool operator>=(Z a, Z b) {
        return a.num >= b.num;
    }
    friend bool operator==(Z a, Z b) {
        return a.num == b.num;
    }
    friend Z operator + (Z a, Z b) {
        return Z((a.num + b.num) % Mod);
    }
    friend Z &operator += (Z &a,Z b) {
        return a = a + b;
    }
    friend Z operator + (Z a, i64 b) {
        return a + Z(b);
    }
    friend Z &operator += (Z &a, i64 b) {
        return a = a + b;
    }
    friend Z &operator ++ (Z &a) {
        return a += 1;
    }
    friend Z operator ++ (Z &a, int) {
        Z copy(a);
        a += 1;
        return copy;
    }
    friend Z operator - (Z a, Z b) {
        return Z(((a.num - b.num) % Mod + Mod) % Mod);
    }
    friend Z &operator -= (Z &a, Z b) {
        return a = a - b;
    }
    friend Z operator - (Z a, i64 b) {
        return a - Z(b);
    }
    friend Z &operator -= (Z &a, i64 b) {
        return a = a - b;
    }
    friend Z &operator -- (Z &a) {
        return a -= 1;
    }
    friend Z operator -- (Z &a, int) {
        Z copy(a);
        a -= 1;
        return copy;
    }
    friend Z operator * (Z a, Z b) {
        return Z((long long)a.num * b.num % Mod);
    }
    friend Z &operator *= (Z &a, Z b) {
        return a = a * b;
    }
    friend Z operator * (Z a, i64 b) {
        return a * Z(b);
    }
    friend Z &operator *= (Z &a, i64 b) {
        return a = a * b;
    }
    Z inv() {
        i64 ans = 1;
        i64 a = num;
        i64 b = Mod - 2; 
        while (b) {
            if (b & 1) ans = ans * a % Mod;
            a = a * a % Mod;
            b >>= 1;
        }
        return Z(ans);
    }
    friend Z operator / (Z a, Z b) {
        return a * b.inv();
    }
    friend Z &operator /= (Z &a, Z b) {
        return a = a / b;
    }
    friend Z operator / (Z a, i64 b) {
        return a / Z(b);
    }
    friend Z &operator /= (Z &a, i64 b) {
        return a = a / b;
    }
    friend std::istream &operator>>(std::istream &is, Z &a) {
        int v;
        is >> v;
        a = Z(v);
        return is;
    }
    friend std::ostream &operator<<(std::ostream &os, const Z &a) {
        return os << a.val();
    }
};

struct Comb {
    using i64 = long long;
    const i64 N, mod = 1000000007;
    vector<i64> fac, invfac;
    Comb(i64 n) : N(n), fac(n + 2), invfac(n + 2) { init(); };
    Comb(int n) : N(n), fac(n + 2), invfac(n + 2) { init(); };
    Comb(double n) : N(i64(n)), fac(i64(n) + 2), invfac(i64(n) + 2) { init(); };
    i64 qpow(i64 x, i64 p) {
        i64 res = 1 % mod; x %= mod;
        for (; p; p >>= 1, x = x * x % mod)
            if (p & 1) res = res * x % mod;
        return res;
    }
    i64 inv(i64 x) { return qpow(x, mod - 2); };
    void init() {
        fac[0] = 1;
        for (i64 i = 1; i <= N; ++i) fac[i] = fac[i - 1] * i % mod;
        invfac[N] = inv(fac[N]);
        for (i64 i = N - 1; i >= 0; --i) invfac[i] = (invfac[i + 1] * (i + 1)) % mod;
    }
    i64 C(i64 n, i64 m) {
        if (!n) {
            return 1;
        }
        if (n < m || m < 0) return 0;
        return fac[n] * invfac[m] % mod * invfac[n - m] % mod;
    }
    i64 A(i64 n, i64 m) {
        if (n < m || m < 0) return 0;
        return fac[n] * invfac[n - m] % mod;
    }
};

constexpr int N = 2e5 + 5;
Comb inv(N);

void solve() {
    cin >> n >> k;

    int u = 0, v = 0;

    vector<int> p(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> p[i];
        u += (p[i] == 0);
        v += (p[i] != 0);
    }

    if (v < (k - 1) / 2) {
        cout << 0 << endl;
        return ;
    }

    Z ans = 0;

    for (int i = (k + 1) / 2; i <= k, i <= v; i++) {
        if (k - i > u || !u) {
            continue;
        }
        ans += inv.C(v, i) * inv.C(u, k - i);
    }

    if (!u && v >= k) {
        ans += inv.C(v, k);
    }

    cout << ans << endl;

}
 
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); 
    init();
    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }
 
    return 0; 
}   
posted on 2024-08-07 23:33  _Reborn  阅读(15)  评论(0编辑  收藏  举报