AGC037B
可以发现直接将每种颜色的第 i 个球分给第 i 个人就可以取到最优解。证明在下面。在这个方案中将每个人的第 i 个球标上 i,能取到最优解的方案中,标 1 的必须仍然是某人的第一个球,标 3 的必须仍是某人的第三个球。O(n) 正反扫两遍分别计算标 2 的球与 1,3 的匹配方法即可。
证明:
把三种颜色的球的位置从小到大排序后,假设为 r1,⋯,rn;g1,⋯,gn;b1,⋯,bn,设 mi=min{ri,gi,bi},Mi=max{ri,gi,bi},设第 i 个人持球最小标号为 ai, 最大标号为 ci。
一方面,把 ri,gi,bi 给第 i 个人可以得到 n∑i=1(Mi−mi)。
另一方面,不妨设 a1<⋯<an,因为前 k 个人最多持有前 k 个红球,绿球,蓝球,所以 ak≤mk,所以 ∑ai≤∑mi,同理 ∑ci≥∑Mi,所以答案不小于 n∑i=1(Mi−mi)。
于是最优解即为 n∑i=1(Mi−mi)。
然后因为每个人不同所以还要乘上 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话