【2025秋120】ACM周测(个人赛,div3)题解
# 【2025秋120】ACM周测(个人赛,div3)题解
# B - A+B+C
# Question
给出三个集合 ,每次询问给出一个 ,问是否存在从 中挑出一个数字 ,使得
# Solution
由于集合大小很小, 得预处理出 可能的所有值,最后 map 判断即可
# Code
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, l;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
cin >> m;
vector<int> b(m);
for (int i = 0; i < m; i++) cin >> b[i];
cin >> l;
vector<int> c(l);
for (int i = 0; i < l; i++) cin >> c[i];
unordered_map<int, int> mp;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k < l; k++)
mp[a[i] + b[j] + c[k]] = 1;
int q; cin >> q;
while (q--) {
int x; cin >> x;
cout << (mp.count(x) ? "Yes" : "No") << endl;
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# C - String Bags
# Question
初始时有一个空字符串 ,此外有 个袋子,每个袋子里面有装有一些字符串
袋子 里包含 个字符串,对于每个袋子,你可以选择两种操作中的一种:
- 支付 元,从袋子中选择一个字符串,将其连接到 的末尾
- 什么也不做
给定一个字符串 , 找到使最终 所需要的最小金额
# Solution
一眼背包问题,定义 表示枚举到第 个袋子,前 个袋子已经把 的字符串组成了的最小代价
对于每个袋子中的一个串 ,如果 ,那么代表可以往后添加 字串,于是转移方程为:
# Code
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int main() {
string T; cin >> T; T = " " + T;
int n; cin >> n;
vector<vector<string> > a(n + 1);
for (int i = 1; i <= n; i++) {
int m; cin >> m;
for (int j = 0; j < m; j++) {
string s; cin >> s;
a[i].push_back(s);
}
}
vector<vector<int> > dp(n + 1, vector<int>(T.size(), INF));
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j < T.size(); j++) {
for (int k = 0; k < a[i].size(); k++) {
if (j + a[i][k].size() - 1 >= T.size()) continue;
if (T.substr(j, a[i][k].size()) == a[i][k])
dp[i][j + a[i][k].size() - 1] = min(dp[i][j + a[i][k].size() - 1], dp[i - 1][j - 1] + 1);
}
}
for (int j = 0; j < T.size(); j++)
dp[i][j] = min(dp[i][j], dp[i - 1][j]);
}
int ans = INF;
for (int i = 1; i <= n; i++)
ans = min(ans, dp[i][T.size() - 1]);
cout << (ans == INF ? -1 : ans) << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# D - Gomamayo Sequence
# Question
给你一个长度为 的字符串 ,它由 0
和 1
组成
长度为 的字符串 由 0
和 1
组成,当且仅当它满足以下条件时,它是一个好字符串:
- 恰好有一个整数 使得 和 的第 个字母 和第 个字符相同
对于每个 ,您可以选择是否执行一次下面的操作:
- 如果 的 个字符是
0
,则将其替换为1
,反之亦然。如果执行此操作,代价是
求使 成为一个好字符串所需的最小总成本
# Solution
考虑到有且仅有一个 ,满足 ,不妨假设 ,那么可知
前面和 后面都是 0101
交替的,我们就可以记录一个交错的前缀和
定义 表示第 个字母,前面都是 0101
交替的,且第 个字母为 0
花费的最小代价, 表示第 个字母,前面都是 0101
交替的,且第 个字母为 1
花费的最小代价
同理, 表示第 个字母,后面都是 0101
交替的,且第 个字母为 0
花费的最小代价
如何计算 ?交错着刷前缀和就好了
for (int i = 1; i <= n; i++) {
pre[i][0] = pre[i - 1][1] + c[i] * (s[i] != '0');
pre[i][1] = pre[i - 1][0] + c[i] * (s[i] != '1');
}
1
2
3
4
2
3
4
最后,关于 只有 , 两种情况,分别枚举一次即可
# Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
string s; cin >> s; s = " " + s;
vector<ll> c(n + 1, 0);
for (int i = 1; i <= n; i++)
cin >> c[i];
vector<vector<ll> > pre(n + 2 , vector<ll>(2, 0)); auto lst = pre;
for (int i = 1; i <= n; i++) {
pre[i][0] = pre[i - 1][1] + c[i] * (s[i] != '0');
pre[i][1] = pre[i - 1][0] + c[i] * (s[i] != '1');
}
for (int i = n; i > 0; i--) {
lst[i][0] = lst[i + 1][1] + c[i] * (s[i] != '0');
lst[i][1] = lst[i + 1][0] + c[i] * (s[i] != '1');
}
ll ans = INF;
//00
for (int i = 1; i < n; i++) {
ll now = c[i] * (s[i] != '0') + c[i + 1] * (s[i + 1] != '0');
now += pre[i - 1][1] + lst[i + 2][1];
ans = min(ans, now);
}
//11
for (int i = 1; i < n; i++) {
ll now = c[i] * (s[i] != '1') + c[i + 1] * (s[i + 1] != '1');
now += pre[i - 1][0] + lst[i + 2][0];
ans = min(ans, now);
}
cout << ans << '\n';
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# E - Another Sigma Problem
# Question
定义 表示把两个十进制接起来
例如
给定数组 ,求:
# Solution
化简
# Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll TT = 998244353;
ll ans = 0;
int main() {
int n; cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
vector<ll> sum(n + 1, 0);
vector<ll> pow10(15, 1);
for (int i = 1; i <= n; i++) sum[i] = (sum[i - 1] + a[i]) % TT;
for (int i = 1; i <= 14; i++) pow10[i] = pow10[i - 1] * 10 % TT;
for (int j = 2; j <= n; j++) {
ans += a[j] * (j - 1);
int num = log10(a[j]) + 1;
ans += sum[j - 1] * pow10[num] % TT;
ans %= TT;
}
cout << ans % TT << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22