1450 words
7 minutes
abc431题解(A~F)
2025-11-09

A - Robot Balance#

签到。

void solve(int cs){
int a, b;
cin >> a >> b;
cout << max(a - b, 0ll) << endl;
}

B - Robot Weight#

map 记一下零件状态,在x上加加减减即可。

void solve(int cs){
int x, n;
cin >> x >> n;
vector<int> w(n + 5);
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
map<int, int> ok;
int q;
cin >> q;
while (q--) {
int id;
cin >> id;
if (ok[id] == 1) {
ok[id] = 0;
x -= w[id];
cout << x << endl;
}
else {
ok[id] = 1;
x += w[id];
cout << x << endl;
}
}
}

C - Robot Factory#

每个身子分配一个他能安装的最大的头,把头和身子从大到小排序后双指针扫一下计数即可。

void solve(int cs){
int n, m, k;
cin >> n >> m >> k;
vector<int> h(n);
vector<int> b(m);
int ph = 0, pb = 0;
for (int i = 0; i < n; i++) {
cin >> h[i];
}
for (int i = 0; i < m; i++) {
cin >> b[i];
}
sort(h.begin(), h.end(), cmp);
sort(b.begin(), b.end(), cmp);
int cnt = 0;
while (ph < n && pb < m) {
if (h[ph] <= b[pb]) {
cnt++;
pb++;
}
ph++;
}
cout << (cnt >= k ? "Yes" : "No") << endl;
}

D - Robot Customize#

假定一开始所有的零件都装在身体上,得到一个基础快乐值 sb=bisb=\sum b_i ,把第 ii 个零件转移到头上相当于我们的基础快乐值加上 del=hibidel=h_i-b_i,同时头部重量加 wiw_i 。考虑总重量为 sw=wisw = \sum w_i ,那头部的重量不能超过 sw2\lfloor\frac{sw}{2}\rfloor

于是我们可以把这道题转换成物品重量为 wiw_i ,价值为 delidel_i ,在容量 sw2\lfloor\frac{sw}{2}\rfloor 下求最大价值和的01背包问题,若最后答案为负数说明把零件放在头上没有快乐值贡献,所以需要将答案与 00maxmax 后和基础快乐值 sbsb 相加。

void solve(int cs){
int n;
cin >> n;
vector<int> w(n), h(n), b(n);
int sw = 0, sb = 0;
for (int i = 0; i < n; i++) {
cin >> w[i] >> h[i] >> b[i];
sw += w[i];
sb += b[i];
}
int m = sw / 2;
vector<int> dp(m + 1, -inf);
dp[0] = 0;
for (int i = 0; i < n; i++) {
int del = h[i] - b[i];
if (del <= 0) continue;
int wt = w[i];
for (int j = m; j >= wt; j--) {
dp[j] = max(dp[j], dp[j - wt] + del);
}
}
int ans = 0;
for (int i = 0; i <= m; i++) {
if (dp[i] > 0) ans = max(ans, dp[i]);
}
cout << ans + sb << endl;
}

E - Reflection on Grid#

抽象成一个 01BFS 问题,一个状态由 x, y, fx,\ y,\ f 三部分组成,x, yx,\ y 为当前格子,ff 为光的入射方向,对于到达的每一个位置,我们枚举是否需要修改,以及修改成那种类型的镜子,如果无需修改,则将光线到达的下一个格子的状态放到队头;如果需要修改,则将光线到达下一个格子的状态放到队尾,跑 BFS 即可。

struct Node {
int x, y, f;
};
string dir = "ABC";
string s[N];
vector<int> d[4][N];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
void nxt(int x, int y, int f, char c, int &nx, int &ny, int &nf) {
if (c == 'A') nf = f;
else if (c == 'B') nf = (5 - f) % 4;
else nf = 3 - f;
nx = x + dx[nf];
ny = y + dy[nf];
}
void solve(int cs) {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> s[i];
s[i] = ' ' + s[i];
}
for (int i = 0; i <= n + 1; i++) {
for (int k = 0; k <= 3; k++) {
d[k][i].assign(m + 2, inf);
}
}
d[0][1][1] = 0;
deque<Node> q;
q.clear();
q.push_back({1, 1, 0});
int ans = inf;
while (q.size()) {
auto [x, y, f] = q.front();
q.pop_front();
int nx, ny, nf, dis;
for (auto c : dir) {
nxt(x, y, f, c, nx, ny, nf);
if (s[x][y] == c) dis = d[f][x][y];
else dis = d[f][x][y] + 1;
if (nx == n && ny == m + 1 && nf == 0) ans = min(ans, dis);
if (nx == 0 || ny == 0 || nx > n || ny > m) continue;
if (dis < d[nf][nx][ny]) {
d[nf][nx][ny] = dis;
if (s[x][y] == c) q.push_front({nx, ny, nf});
else q.push_back({nx, ny, nf});
}
}
}
cout << ans << endl;
}

F - Almost Sorted 2#

先将数组从小到大排序,我们发现任意一个小于 aida_i-d 的值不可能出现在 aia_i 之后,否则从 aia_i 向下到该值至少会出现一次相邻下降大于 dd ,因此令 posipos_i 为使 aposiaida_{pos_i} \geq a_i-d 的最小索引,在 1i1\sim i 的所有值中索引 1posi11\sim pos_i-1 的元素必须出现在 aia_i 以前。因此,当我们按升序把这 ii 个元素放到最终序列时,aia_i 在这 ii 个元素中的合法插入位置数为 i(posi1)=iposi+1i-(pos_i-1)=i-pos_i+1 。将对所有 ii 的选择数相乘,就得到把排序后元素视为可区分物件的排列数。

因为原题中相同元素不可区分,所以要进行去重,如果某个值 vv 在原数组中出现了 cntvcnt_v 次,上面的计数把这 cntvcnt_v 个相同值当作 cntvcnt_v 个不同对象来计数(即标号化),导致重复计数 cntv!cnt_v! 倍。

故最终答案为:

(i=1N(ili+1))×v(cntv!)1(mod998244353).\left(\prod_{i=1}^N (i - l_i + 1)\right) \times \prod_{v} (cnt_v!)^{-1} \pmod{998244353}.
int qpow(int a, int x, int mod) {
int res = 1LL;
while (x) {
if (x % 2)
res = res * a % mod;
a = a * a % mod;
x /= 2;
}
return res;
}
int fac[N], invFac[N];
void init() {
fac[0] = 1;
for (int i = 1; i < N; ++i) {
fac[i] = (fac[i - 1] * i) % MOD;
}
invFac[N - 1] = qpow(fac[N - 1], MOD - 2, MOD);
for (int i = N - 2; i >= 0; --i) {
invFac[i] = (invFac[i + 1] * (i + 1)) % MOD;
}
}
void solve(int cs){
init();
int n, d;
cin >> n >> d;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a.begin(), a.end());
int ans = 1;
for (int i = 0; i < n; i++) {
int nd = a[i] - d;
int pos = lower_bound(a.begin(), a.end(), nd) - a.begin();
int pk = i - pos + 1;
if (pk <= 0) {
ans = 0;
break;
}
ans = (ans * (pk % MOD)) % MOD;
}
int id = 0;
while (id < n) {
int j = id + 1;
while (j < n && a[j] == a[id]) {
j++;
}
int cnt = j - id;
ans = (ans * invFac[cnt]) % MOD;
id = j;
}
cout << ans % MOD << endl;
}
abc431题解(A~F)
https://fuwari.vercel.app/posts/abc/abc431/
Author
P19E99
Published at
2025-11-09
License
CC BY-NC-SA 4.0