Codeforces Round #884 (Div. 1 + Div. 2) A-E
A
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { int a, b; cin >> a >> b; cout << a + b << '\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; }
B
题意
构造一个长为 的排列,使得 为质数的子区间的个数最多。
题解
知识点:构造。
当 时,只能是 和 ,接下来讨论 的情况。
显然, 一定要在区间内,因此假设 的位置是 ,那么个数最多为 。
注意到,只需要将 放在两侧,即可到达上限。
为了使得上限最大,令 ,取 即可。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { int n; cin >> n; if (n == 1) { cout << "1" << '\n'; return true; } if (n == 2) { cout << "1 2" << '\n'; return true; } int pos = 4; for (int i = 1;i <= n;i++) { if (i == 1) cout << "2" << ' '; else if (i == (n + 1 >> 1)) cout << "1" << ' '; else if (i == n) cout << "3" << '\n'; else cout << pos++ << ' '; } 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> using namespace std; using ll = long long; bool solve() { int n; cin >> n; array<ll, 2> ans{}; int mx = -1e9; for (int i = 1;i <= n;i++) { int x; cin >> x; mx = max(mx, x); ans[i & 1] += max(x, 0); } ll mxans = max(ans[0], ans[1]); cout << (mxans ? mxans : mx) << '\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> using namespace std; using ll = long long; void get_factor(int n, vector<int> &factor) { for (int i = 1;i * i <= n;i++) { if (n % i == 0) { factor.push_back(i); if (n / i != i) factor.push_back(n / i); } } } bool solve() { int n; cin >> n; vector<int> factor; get_factor(n, factor); sort(factor.begin(), factor.end()); string s; vector<int> f(n + 1); for (int i = 1;i <= n;i++) { vector<int> vis(26); for (auto val : factor) { if (i - val <= 0) break; vis[f[i - val]] = 1; } for (int j = 0;j < 26;j++) { if (!vis[j]) { s += 'a' + j; f[i] = j; break; } } } cout << s << '\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> using namespace std; using ll = long long; bool solve() { int n; cin >> n; int pos = 1; while (n % pos == 0) pos++; for (int i = 1;i <= n;i++) cout << (char)('a' + (i - 1) % pos); 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; }
E
题意
一个 的矩阵,若满足下列要求,则是好的:
- 矩阵元素只能是
A,B,C
三个字符的一个。 - 相邻元素不能一样。
- 任何 的子矩阵必须包含 个不同的字符。
问能否构造一个好的矩阵,同时这个矩阵要满足 个约束,每个约束表达为 ,表示这两个位置的元素要一样,保证给出的这两个位置是对角相邻的。
题解
知识点:构造,数论,并查集。
我们将 A,B,C
换为数字 ,观察好的矩阵中某个 子矩阵的性质,例如:
我们发现,任意 的子矩阵,一定满足:
即子矩阵左两个元素的差和右两个元素的差是模 相等的。
同时,我们根据这个式子在相同的两行 上对 递推,可以得到这两行的每一列两个元素的差都是模 相等的,其值为 或 。假设我们用 代表 两行,那么结论是对于 每一行都只有一个值。
同理,将公式变形,可以在相同的两列上对 递推,也可以得到对于 每一列都只有一个值。
接下来讨论行和列的值之间的关系。我们可以观察到,一个子矩阵 中,若相等的元素是左上 和右下 ,那么第 行的值和第 列的值一定不同,否则是相同的。
因此, 个约束实际上规定的是,某行和某列的值必须相同或者不同,这就变成一个二分图判定的变体了(普通二分图只有邻接必须不同的要求,没有必须相同要求),可以用染色法解决(表示相同的边染同色,不同的边染异色)。当然,也可以用种类并查集解决,这里用的是这种方法。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; struct DSU { vector<int> fa; DSU(int n = 0) { init(n); } void init(int n) { fa.assign(n + 1, 0); iota(fa.begin(), fa.end(), 0); } int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } bool same(int x, int y) { return find(x) == find(y); } void merge(int x, int y) { fa[find(x)] = find(y); } }; tuple<int, int, int> a[4007]; bool solve() { int n, m, k; cin >> n >> m >> k; for (int i = 1;i <= k;i++) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; a[i] = { x1,min(y1,y2),y1 < y2 }; } DSU dsu(2 * (n + m)); for (int i = 1;i <= k;i++) { auto [x, y, type] = a[i]; if (dsu.same(x, y + n + !type * (n + m))) return false; dsu.merge(x, y + n + type * (n + m)); dsu.merge(x + n + m, y + n + !type * (n + m)); } 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; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17555182.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧