Codeforces Round #570 (Div. 3)
比赛链接:https://codeforces.com/contest/1183
A - Nearest Interesting Number
题意
寻找不小于 $a$ 的最小的数位之和为 $4$ 的倍数的数。(1 ≤ a ≤ 1000)
代码
#include <bits/stdc++.h> using namespace std; int sum(int n) { int res = 0; while (n) { res += n % 10; n /= 10; } return res; } int main() { int a; cin >> a; for (int i = a; i <= 1003; i++) { if (sum(i) % 4 == 0) { cout << i; break; } } }
B - Equalize Prices
题意
有一大小为 $n$ 的数组 $a$,每个元素变化的绝对值不超过 $k$,该数组的所有元素能否变为同一个值。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int n, k; cin >> n >> k; int mi = 1e9, mx = 0; for (int i = 0; i < n; i++) { int x; cin >> x; mi = min(mi, x); mx = max(mx, x); } if (mi + k >= mx - k) cout << mi + k << "\n"; else cout << -1 << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
C - Computer Game
题意
电脑还有 $k$ 点电量,一个游戏有 $n$ 轮,每轮可进行如下选择:
- 如果剩余电量大于 $a$,可以玩一轮,消耗 $a$ 点电量
- 如果剩余电量大于 $b$,可以充电玩一轮,消耗 $b$ 点电量
- 如果剩余电量小于等于 $a$ 或 $b$,终止游戏
判断是否可以玩完 $n$ 轮游戏,如果可以,最多能不充电玩几轮。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int k, n, a, b; cin >> k >> n >> a >> b; --k; if (k / b >= n) { int ex = k - min(n, k / b) * b; cout << min(n, ex / (a - b)) << "\n"; } else cout << -1 << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
D - Candy Box (easy version)
题意
给出 $n$ 个礼物的种类,选择一些种类的礼物,要求不同种类的礼物数量不同,问所选礼物的数量最多为多少。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; int cnt[n] = {}; for (int i = 0; i < n; i++) { int a; cin >> a; --a; cnt[a]++; } sort(cnt, cnt + n, greater<int>()); int ans = 0; int p = 0; for (int i = n; i > 0; i--) { if (cnt[p] >= i) { ans += i; ++p; } } cout << ans << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
E - Subsequences (easy version)
见 H 。
F - Topforces Strikes Back
题意
从 $n$ 个数中最多选 $3$ 个数,要求所选数两两不整除(即互质),问所选数之和的最大值。
题解
怎么说呢...有些玄学...
大致来讲就是贪心地选择可以选择的最大的数,然后特判一下 $2,3,5$ 的情况,因为 $\frac{1}{2} + \frac{1}{3} + \frac{1}{5} > 1$ 。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; set<int> st; for (int i = 0; i < n; i++) { int x; cin >> x; st.insert(x); } int ans = 0; int mx = *st.rbegin(); if (mx % 2 == 0 and mx % 3 == 0 and mx % 5 == 0) { if (st.count(mx / 2) and st.count(mx / 3) and st.count(mx / 5)) { ans = max(ans, mx / 2 + mx / 3 + mx /5); } } vector<int> res; while (!st.empty() and res.size() < 3) { int x = *st.rbegin(); st.erase(prev(st.end())); bool ok = true; for (auto it : res) ok &= (it % x != 0); if (ok) res.push_back(x); } ans = max(ans, accumulate(res.begin(), res.end(), 0)); cout << ans << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
G - Candy Box (hard version)
题意
给出 $n$ 个礼物的种类和是否想保留,选择一些种类的礼物,要求不同种类的礼物数量不同,问所选礼物的数量、保留礼物的数量最多分别为多少。
代码(priority_queue)
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; int cnt[n] = {}; int cnt_good[n] = {}; for (int i = 0; i < n; i++) { int a, f; cin >> a >> f; --a; cnt[a]++; if (f) cnt_good[a]++; } vector<int> types[n + 1]; for (int i = 0; i < n; i++) { types[cnt[i]].push_back(cnt_good[i]); } int ans1 = 0, ans2 = 0; priority_queue<int> cur; for (int i = n; i > 0; i--) { for (auto j : types[i]) cur.push(j); if (!cur.empty()) { ans1 += i; ans2 += min(i, cur.top()); cur.pop(); } } cout << ans1 << ' ' << ans2 << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
代码(multiset)
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; int cnt[n] = {}; int cnt_good[n] = {}; for (int i = 0; i < n; i++) { int a, f; cin >> a >> f; --a; cnt[a]++; if (f) cnt_good[a]++; } vector<int> types[n + 1]; for (int i = 0; i < n; i++) { types[cnt[i]].push_back(cnt_good[i]); } int ans1 = 0, ans2 = 0; multiset<int> cur; for (int i = n; i > 0; i--) { for (auto j : types[i]) cur.insert(j); if (!cur.empty()) { int mx = *cur.rbegin(); ans1 += i; ans2 += min(i, mx); cur.erase(cur.find(mx)); } } cout << ans1 << ' ' << ans2 << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
H - Subsequences (hard version)
题意
给出一个字符串 $s$,选取一个子序列的花费为选取该序列所需去掉的字符个数,问选取 $k$ 个不同子序列的最少花费为多少。
代码
#include <bits/stdc++.h> using ll = long long; using namespace std; const ll INF = 1e12; int main() { ll n, k; cin >> n >> k; --k; //原字符串算一个序列,不需要去掉任何字符 string s; cin >> s; int lst[n][26] = {}; fill(*lst, *lst + n * 26, -1); for (int i = 0; i < n; i++) { for (int j = 0; j < 26; j++) { if (i > 0) lst[i][j] = lst[i - 1][j]; } lst[i][s[i] - 'a'] = i; } ll dp[n + 1][n + 1] = {}; for (int i = 0; i < n; i++) dp[i][1] = 1; for (int len = 2; len < n; len++) { for (int i = 1; i < n; i++) { for (int j = 0; j < 26; j++) { if (lst[i - 1][j] != -1) { dp[i][len] = min(INF, dp[i][len] + dp[lst[i - 1][j]][len - 1]); } } } } ll ans = 0; for (int len = n - 1; len >= 1; len--) { ll cnt = 0; for (int j = 0; j < 26; j++) { if (lst[n - 1][j] != -1) { cnt += dp[lst[n - 1][j]][len]; } } if (cnt >= k) { ans += k * (n - len); k = 0; break; } else { ans += cnt * (n - len); k -= cnt; } } if (k == 1) { ans += n; --k; } if (k > 0) cout << -1 << "\n"; else cout << ans << "\n"; }

浙公网安备 33010602011771号