AGC037B

可以发现直接将每种颜色的第 \(i\) 个球分给第 \(i\) 个人就可以取到最优解。证明在下面。在这个方案中将每个人的第 \(i\) 个球标上 \(i\),能取到最优解的方案中,标 \(1\) 的必须仍然是某人的第一个球,标 \(3\) 的必须仍是某人的第三个球。\(\mathcal O(n)\) 正反扫两遍分别计算标 \(2\) 的球与 \(1,3\) 的匹配方法即可。

证明:

把三种颜色的球的位置从小到大排序后,假设为 \(r_1,\cdots,r_n;g_1,\cdots,g_n;b_1,\cdots,b_n\),设 \(m_i=\min\left\{r_i,g_i,b_i\right\},M_i=\max\left\{r_i,g_i,b_i\right\}\),设第 \(i\) 个人持球最小标号为 \(a_i\), 最大标号为 \(c_i\)

一方面,把 \(r_i,g_i,b_i\) 给第 \(i\) 个人可以得到 \(\sum\limits_{i=1}^{n}(M_i-m_i)\)

另一方面,不妨设 \(a_1\lt\cdots\lt a_n\),因为前 \(k\) 个人最多持有前 \(k\) 个红球,绿球,蓝球,所以 \(a_k\le m_k\),所以 \(\sum a_i\le \sum m_i\),同理 \(\sum c_i\ge \sum M_i\),所以答案不小于 \(\sum\limits_{i=1}^{n}(M_i-m_i)\)

于是最优解即为 \(\sum\limits_{i=1}^{n}(M_i-m_i)\)

然后因为每个人不同所以还要乘上 \(n!\)

Code:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int N = 300005, mod = 998244353;
char s[N];
int n, ty[N];
vector <int> pos[3];

int main() {
	scanf("%d%s", &n, s + 1);
	pos[0].pb(0), pos[1].pb(0), pos[2].pb(0);
	for (int i = 1; i <= n * 3; ++i) {
		if (s[i] == 'R') pos[0].pb(i);
		if (s[i] == 'G') pos[1].pb(i);
		if (s[i] == 'B') pos[2].pb(i);
	}
	int ans = 1;
	for (int i = 1; i <= n; ++i) {
		int a = pos[0][i], b = pos[1][i], c = pos[2][i];
		if (a > b) swap(a, b); if (a > c) swap(a, c); if (b > c) swap(b, c);
		ty[a] = 1, ty[b] = 2, ty[c] = 3;
		ans = 1ll * ans * i % mod;
	}
	for (int i = n * 3, cnt = 0; i; --i) {
		if (ty[i] == 3) ++cnt;
		if (ty[i] == 2) ans = 1ll * ans * cnt % mod, --cnt;
	}
	for (int i = 1, cnt = 0; i <= n * 3; ++i) {
		if (ty[i] == 1) ++cnt;
		if (ty[i] == 2) ans = 1ll * ans * cnt % mod, --cnt;
	}
	printf("%d", ans);
	return 0;
}
posted @ 2022-11-06 20:55  Kobe303  阅读(19)  评论(0编辑  收藏  举报