AT_abc453_e [ABC453E] Team Division 题解
思路
首先会想到枚举队伍 \(A\) 中人的个数。这样也就可以得出队伍 \(B\) 中的人的个数。接着我们就可以将人分为四类:都不行的(这种情况要舍)、只能放在队伍 \(A\) 里的、只能放在队伍 \(B\) 里的、和两个队伍都能放的。所以实际上就是看两个队伍都能放的人中的方案数。这就是一个简单组合计数。
怎么得到每一类中的人呢?差分即可。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5, mod = 998244353;
int n;
int l[N], r[N], cnt1[N], cnt2[N], cnt3[N], fact[N], inv[N];
int fastPow(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int C(int n, int m)
{
if (n < 0 || m < 0 || n < m) return 0;
return ((fact[n] * inv[m] % mod) * inv[n - m]) % mod;
}
signed main()
{
fact[0] = 1;
for (int i = 1; i < N - 1; i++)
fact[i] = fact[i - 1] * i % mod;
inv[N - 2] = fastPow(fact[N - 2], mod - 2);
for (int i = N - 3; i >= 0; i--)
inv[i] = inv[i + 1] * (i + 1) % mod;
scanf("%lld", &n);
for (int i = 1; i <= n; i++)
{
scanf("%lld%lld", &l[i], &r[i]);
cnt1[l[i]]++, cnt1[r[i] + 1]--;
cnt2[n - r[i]]++, cnt2[n - l[i] + 1]--;
int tmpl = max(l[i], n - r[i]), tmpr = min(r[i], n - l[i]);
if (tmpl <= tmpr) cnt3[tmpl]++, cnt3[tmpr + 1]--;
}
for (int i = 1; i <= n; i++)
{
cnt1[i] += cnt1[i - 1];
cnt2[i] += cnt2[i - 1];
cnt3[i] += cnt3[i - 1];
}
int ans = 0;
for (int i = 1; i < n; i++)
{
int cntA = cnt1[i] - cnt3[i], cntB = cnt2[i] - cnt3[i];
if (cntA + cntB + cnt3[i] == n) ans = (ans + C(cnt3[i], i - cntA)) % mod;
}
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号