Codeforces Round #834 (Div. 3) A-G
A
题目
知识点:模拟。
确定开头字母,然后循环比较即可。
时间复杂度
空间复杂度
题解
#include <bits/stdc++.h> #define ll long long using namespace std; bool solve() { string s; cin >> s; string t = "Yes"; int pos = -1; if (s[0] == t[0]) pos = 0; else if (s[0] == t[1]) pos = 1; else if (s[0] == t[2]) pos = 2; else return false; for (auto ch : s) { if (ch != t[pos]) return false; pos = (pos + 1) % 3; } cout << "YES" << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << "NO" << '\n'; } return 0; }
B
题目
知识点:枚举。
找到总和等于 的排列,其中 是原来序列的和。这个排列的最大数字不能小于原来序列里的最大数字,否则不合法。
时间复杂度
空间复杂度
题解
#include <bits/stdc++.h> #define ll long long using namespace std; bool solve() { int m, s; cin >> m >> s; int mx = 0, sum = 0; for (int i = 1;i <= m;i++) { int x; cin >> x; sum += x; mx = max(x, mx); } int ans = -1; for (int i = 1;i <= 70;i++) { if (i * (i + 1) / 2 == sum + s) { ans = i; break; } } if (ans >= mx) cout << "YES" << '\n'; else cout << "NO" << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
C
题目
知识点:贪心。
分类讨论:
- ,不用操作。
- ,一次操作。
- 先将 变 (或 ),再将 (或 )变成 ,两次操作(如果可以的话)。
- 先将 变 (或 ),再将 (或 )变成 (或 ),再将 (或 )变成 ,三次操作(如果可以的话)。
- 无解,因为 变换到 或 将会拥有与 的最大距离,再不行就无解。
时间复杂度
空间复杂度
题解
#include <bits/stdc++.h> #define ll long long using namespace std; bool solve() { int l, r, x; int a, b; cin >> l >> r >> x; cin >> a >> b; if (a == b) cout << 0 << '\n'; else if (abs(a - b) >= x) cout << 1 << '\n'; else if (a - l >= x && b - l >= x || r - a >= x && r - b >= x) cout << 2 << '\n'; else if (a - l >= x && r - l >= x && r - b >= x || r - a >= x && r - l >= x && b - l >= x) cout << 3 << '\n'; else cout << -1 << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
D
题目
知识点:数论,贪心。
显然尽可能配对 和 因子,随后尽可能乘 。
先找到 中已有的 ,因子数量,然后先用 配平因子数(这样操作的得到的 最小)。
之后,给 乘 直到再次操作会超过 。
最后把 加倍到最大值 内最大值。
时间复杂度
空间复杂度
题解
#include <bits/stdc++.h> #define ll long long using namespace std; bool solve() { int n, m; cin >> n >> m; int t = n; int c2 = 0, c5 = 0; while (t % 2 == 0) t /= 2, c2++; while (t % 5 == 0) t /= 5, c5++; int mul = 1; while (c2 < c5 && mul * 2LL <= m) mul *= 2, c2++; while (c2 > c5 && mul * 5LL <= m) mul *= 5, c5++; while (mul * 10LL <= m) mul *= 10; cout << 1LL * n * (m / mul) * mul << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
E
题目
显然贪心策略是从小到大吸收,考虑道具使用顺序。
方法一
知识点:枚举,dfs。
只有三个道具,直接搜索所有使用顺序即可,每次先把能吸收的吸收了。
时间复杂度
空间复杂度
方法二
知识点:线性dp。
设 表示吸收了前 个人, 倍道具剩 个, 倍道具剩 个的最大能量。
转移时,先从吸收了 个人的状态转移到吸收了 个人的状态,再考虑吸收了 个人的状态后使用道具的情况。
使用道具时的转移不需要考虑转移顺序。某个状态被其他的状态更新后,再使用道具的状态一定会被更新他的状态包括,因此不需要考虑更新顺序。
时间复杂度
空间复杂度
题解
方法一
#include <bits/stdc++.h> #define ll long long using namespace std; int n; int a[200007]; int dfs(int pos, int cntg, int cntb, ll h) { while (pos <= n && h > a[pos]) h += a[pos++] / 2; int mx = pos - 1; if (cntg >= 1) mx = max(mx, dfs(pos, cntg - 1, cntb, h * 2)); if (cntb >= 1) mx = max(mx, dfs(pos, cntg, cntb - 1, h * 3)); return mx; } bool solve() { int h; cin >> n >> h; for (int i = 1;i <= n;i++) cin >> a[i]; sort(a + 1, a + n + 1); cout << dfs(1, 2, 1, h) << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
方法二
#include <bits/stdc++.h> #define ll long long using namespace std; int a[200007]; ll f[200007][3][2]; bool solve() { int n, h; cin >> n >> h; for (int i = 1;i <= n;i++) cin >> a[i]; sort(a + 1, a + n + 1); for (int i = 1;i <= n;i++) for (int j = 0;j <= 2;j++) for (int k = 0;k <= 1;k++) f[i][j][k] = 0; f[0][2][1] = h; f[0][1][1] = h * 2; f[0][2][0] = h * 3; f[0][0][1] = h * 4; f[0][1][0] = h * 6; f[0][0][0] = h * 12; for (int i = 1;i <= n;i++) { for (int j = 0;j <= 2;j++) for (int k = 0;k <= 1;k++) if (f[i - 1][j][k] > a[i]) f[i][j][k] = max(f[i][j][k], f[i - 1][j][k] + a[i] / 2); for (int j = 0;j <= 2;j++) { for (int k = 0;k <= 1;k++) { if (j >= 1) f[i][j - 1][k] = max(f[i][j - 1][k], f[i][j][k] * 2); if (k >= 1) f[i][j][k - 1] = max(f[i][j][k - 1], f[i][j][k] * 3); if (j >= 2) f[i][j - 2][k] = max(f[i][j - 2][k], f[i][j][k] * 4); if (j >= 1 && k >= 1) f[i][j - 1][k - 1] = max(f[i][j - 1][k - 1], f[i][j][k] * 6); if (j >= 2 && k >= 1) f[i][j - 2][k - 1] = max(f[i][j - 2][k - 1], f[i][j][k] * 12); } } } for (int i = n;i >= 0;i--) for (int j = 0;j <= 2;j++) for (int k = 0;k <= 1;k++) if (f[i][j][k]) { cout << i << '\n'; return true; } return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
F
题目
知识点:贪心,枚举。
显然答案不会大于等于 ,即只需要考虑 关于缺失数字的大小即可,用 set
存出现过的数。
如果没有小于 的缺失数字,就不需要进位,设最大的缺失数字为 (不存在则设为 ),答案为 。
如果有小于 的缺失数字,则必须进位。进位后,一定会出现 以及模拟进位后变化的最高位的数字,需要纳入 set
。随后找到小于 的最大缺失数字 (不存在则设为 ),答案为 。
因为给出的数字最多只有 个,所以每次找数字的次数不会超过 次。
时间复杂度
空间复杂度
题解
#include <bits/stdc++.h> #define ll long long using namespace std; int a[107]; bool solve() { int n, p; cin >> n >> p; for (int i = 1;i <= n;i++) cin >> a[i]; set<int> st; for (int i = 1;i <= n;i++) st.insert(a[i]); bool cf = 0; for (int i = a[n];i >= 0 && !cf;i--) cf |= !st.count(i); if (cf) { st.insert(0); for (int i = n - 1;i >= 0;i--) { if (a[i] + 1 < p) { st.insert(a[i] + 1); break; } } int mx = a[n] - 1; while (mx > 0 && st.count(mx)) mx--; cout << mx + p - a[n] << '\n'; } else { int mx = p - 1; while (mx > a[n] && st.count(mx)) mx--; cout << mx - a[n] << '\n'; } return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
G
题目
知识点:构造,二分,贪心。
显然, 最优,接下来考虑 。
首先,我们希望出现在前面的数字尽可能小,但因为留下的数字是较大的,不一定能让后面数字有解。于是,若要确定这个数字,那么就必须每次都需要检查一遍后面的数字是否还有解,这样很难以较小复杂度实现。
但是,我们知道出现在后面的数字要尽可能大,我们可以从后往前确定数字,这样就尽可能保留了小的数字,使得前面的数有解。并且,保留的数字不会比这种方案更小,因此如果前面的数字还是无解,那就真的无解。
因此,我们先把 到 存在 set
中,把出现过的数字删除。如果删除的数字已经删过,那么不可能是个排列,所以无解。然后,从后往前,确定未出现的数中小于 的最大数当作 ,如果没有则无解。
时间复杂度
空间复杂度
#include <bits/stdc++.h> #define ll long long using namespace std; int a[200007], b[100007]; bool solve() { int n; cin >> n; for (int i = 1;i <= n / 2;i++) cin >> b[i], a[i * 2] = b[i]; set<int> st; for (int i = 1;i <= n;i++) st.insert(i); for (int i = 1;i <= n / 2;i++) { if (!st.count(b[i])) return false; st.erase(b[i]); } for (int i = n / 2;i >= 1;i--) { auto pos = st.lower_bound(b[i]); if (pos == st.begin()) return false; a[i * 2 - 1] = *prev(pos); st.erase(prev(pos)); } for (int i = 1;i <= n;i++) cout << a[i] << ' '; cout << '\n'; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16906184.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧