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;
}
posted @ 2026-04-25 15:17  lucasincyber  阅读(14)  评论(0)    收藏  举报