Team Division

Team Division

差分性质
cntA代表 固定一个队伍数量为i时,有多少个人可以到这个队伍中
both代表 能去i 也能去n-i
这样就可以枚举A = i, B = n - i的情况,直接计算即可

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;
const ll INF = 1e9;
const int N = 2e5 + 10;
ll fact[N], invfact[N];

ll modpow(ll a, ll b) {
    ll r = 1;
    while(b) {
        if(b & 1) r = r * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return r;
}
void init() {
    fact[0] = 1;
    for(int i = 1; i < N; i ++) fact[i] = fact[i-1] * i % MOD;
    invfact[N-1] = modpow(fact[N-1], MOD-2);
    for(int i = N - 2; i >= 0; i --) invfact[i] = invfact[i+1]*(i+1) % MOD;
}
ll C(int a, int b) {
    return fact[a] * invfact[b] % MOD * invfact[a-b] % MOD;
}

void solve() {
    init();
    int n; cin >> n;
    vector<int> cntA(n + 1, 0), both(n + 1, 0);
    for(int i = 1; i <= n; i ++) {
        int l, r; cin >> l >> r;
        cntA[l] ++, cntA[r + 1] --;
        int left = max(n - r, l), right = min(n - l, r);
        if(left <= right) both[left] ++, both[right + 1] --;
    }
    for(int i = 1; i <= n; i ++) cntA[i] += cntA[i - 1], both[i] += both[i - 1];

    ll ans = 0;
    for(int i = 1; i < n; i ++) {
        if(n - cntA[i] - cntA[n - i] + both[i] > 0) continue;
        
        if(cntA[i] < i) continue;
        int must = cntA[i] - both[i];
        int x = i - must;
        if(x < 0 || x > both[i]) continue;
        ans = (ans + C(both[i], x)) % MOD;
    }
    cout << ans << "\n";
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
    return 0;
}
posted @ 2026-09-25 09:22  thenrify  阅读(7)  评论(0)    收藏  举报