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
题意
构造一个长为 \(n\) 的排列,使得 \(MEX\) 为质数的子区间的个数最多。
题解
知识点:构造。
当 \(n \leq 2\) 时,只能是 \(1\) 和 \(1,2\) ,接下来讨论 \(n \geq 3\) 的情况。
显然, \(1\) 一定要在区间内,因此假设 \(1\) 的位置是 \(pos\) ,那么个数最多为 \(pos(n-pos+1) - [n+1 \in prime]\) 。
注意到,只需要将 \(2,3\) 放在两侧,即可到达上限。
为了使得上限最大,令 \(pos = n-pos+1\) ,取 \(pos = \left\lfloor \dfrac{n+1}{2} \right\rfloor\) 即可。
时间复杂度 \(O(n)\)
空间复杂度 \(O(1)\)
代码
#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
题意
给定一个长为 \(n\) 的整数数组 \(a\) ,每次可以执行一个操作:选择一个位置 \(i\) ,删除 \(a_i\) ,并合并 \(a_{i-1}\) 和 \(a_{i+1}\) 变为 \(a_{i-1} + a_{i+1}\) 。
需要执行操作,直到数组只剩 \(1\) 个数字,问最后这个数字最大是多少。
题解
知识点:贪心,数学。
注意到,只有同奇偶的位置才有机会合并,不同奇偶的一定合并不到。
同时,存在操作,使得任意同奇偶位置的数字合并在一起,因此答案是取奇数位置的正数之和与偶数位置的正数之和的最大值。特别地,若不存在正数,取所有元素里的最大值即可。
时间复杂度 \(O(n)\)
空间复杂度 \(O(1)\)
代码
#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
题意
一个 \(r \times c\) 的字符矩阵 \(A\) 的行主序字符串是将 \(A\) 的所有行拼接得到的,形如:
\]
一个字符矩阵,若存在相邻两个字符是一样的,那么这个字符矩阵是坏的。
现在需要构造一个长为 \(n\) 的字符串 \(s\) ,使得所有行主序是这个字符串的字符矩阵不是坏的。
题解
方法一
知识点:构造,数论。
一个朴素的想法是,对于任何 \(n\) 的因子 \(d\) ,字符 \(s_i\) 不能和 \(s_{i-d}\) 相同。
因此,我们先可以求出 \(n\) 的所有因子 \(d\) 。构造一个字符时,枚举所有因子 \(d\) ,记录 \(d\) 个字符之前的字符是什么,然后贪心取最小的一个没出现过的字符即可保证字母种类最少,时间复杂度是 \(O(n \sqrt n)\) 的。
但众所周知因子的上界 \(O(\sqrt n)\) 是个很松的上界,实际上 \(10^9\) 内的数字正因数最多有 \(1344\) 个,过这道题是轻轻松松的。
时间复杂度 \(O(n \sqrt n)\)
空间复杂度 \(O(n)\)
方法二
知识点:构造,数论。
基于方法一的朴素想法,我们发现第一个不是 \(n\) 因子的数 \(c\) 是字母种类的下限。因为小于 \(c\) 的都是 \(n\) 的因子,这导致一个字母之前连续 \(c-1\) 个字母必须互不相同。
我们尝试以 \(c\) 为周期构造字符串,验证下限是否合法。以 \(c\) 为周期构造,那么只存在 \(s_i = s_{i+c}(1 \leq i \leq n-c)\) ,但因为 \(kc(k \geq 1)\) 不是 \(n\) 的因子,因此不存在一个因子 \(d\) 使得 \(s_i = s_{i+d}\) ,所以 \(c\) 是合法的。
根据官方题解,上面说的还可以用图论来解释。
将 \(n\) 个字符看作点,需要满足互不相同的限制是边,那么问题等价于图的最小染色问题(颜色种类最少)。
显然,色数(最小染色的颜色数)一定是大于等于团数(最大团的点数),那么我们可以找到最大团(最大完全子图)包含 \(c\) 个点,因此色数一定大于等于 \(c\) 。
我们令色数为 \(c\) ,上面的证明可以理解为不存在一个因子 \(d\) 使得 \(s_i,s_{i+d}\) 之间存在边,因此 \(c\) 是合法的。
时间复杂度 \(O(n)\)
空间复杂度 \(O(1)\)
代码
方法一
#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
题意
一个 \(n \times m\) 的矩阵,若满足下列要求,则是好的:
- 矩阵元素只能是
A,B,C
三个字符的一个。 - 相邻元素不能一样。
- 任何 \(2 \times 2\) 的子矩阵必须包含 \(3\) 个不同的字符。
问能否构造一个好的矩阵,同时这个矩阵要满足 \(k\) 个约束,每个约束表达为 \((x_1,y_1),(x_2,y_2)\) ,表示这两个位置的元素要一样,保证给出的这两个位置是对角相邻的。
题解
知识点:构造,数论,并查集。
我们将 A,B,C
换为数字 \(0,1,2\) ,观察好的矩阵中某个 \(2 \times 2\) 子矩阵的性质,例如:
0& 1&\\
1& 2&
\end{matrix}
\]
我们发现,任意 \(2 \times 2\) 的子矩阵,一定满足:
a_{i,j} - a_{i+1,j} \equiv a_{i,j+1} - a_{i+1,j+1} \pmod 3
\end{align}
\]
即子矩阵左两个元素的差和右两个元素的差是模 \(3\) 相等的。
同时,我们根据这个式子在相同的两行 \(i,i+1\) 上对 \(j\) 递推,可以得到这两行的每一列两个元素的差都是模 \(3\) 相等的,其值为 \(1\) 或 \(2\) 。假设我们用 \(i\) 代表 \(i,i+1\) 两行,那么结论是对于 \(i < n\) 每一行都只有一个值。
同理,将公式变形,可以在相同的两列上对 \(i\) 递推,也可以得到对于 \(j<m\) 每一列都只有一个值。
接下来讨论行和列的值之间的关系。我们可以观察到,一个子矩阵 \((i,j)\) 中,若相等的元素是左上 \((i,j)\) 和右下 \((i+1,j+1)\) ,那么第 \(i\) 行的值和第 \(j\) 列的值一定不同,否则是相同的。
因此, \(k\) 个约束实际上规定的是,某行和某列的值必须相同或者不同,这就变成一个二分图判定的变体了(普通二分图只有邻接必须不同的要求,没有必须相同要求),可以用染色法解决(表示相同的边染同色,不同的边染异色)。当然,也可以用种类并查集解决,这里用的是这种方法。
时间复杂度 \(O(n+m+k\log (n+m))\)
空间复杂度 \(O(n+m+k)\)
代码
#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;
}
Codeforces Round #884 (Div. 1 + Div. 2) A-E的更多相关文章
- Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship
Problem Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...
- Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)
Problem Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...
- Educational Codeforces Round 43 (Rated for Div. 2)
Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...
- Educational Codeforces Round 35 (Rated for Div. 2)
Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...
- Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings
Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...
- Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes
Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...
- Educational Codeforces Round 63 (Rated for Div. 2) 题解
Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...
- Educational Codeforces Round 39 (Rated for Div. 2) G
Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...
- Educational Codeforces Round 48 (Rated for Div. 2) CD题解
Educational Codeforces Round 48 (Rated for Div. 2) C. Vasya And The Mushrooms 题目链接:https://codeforce ...
- Educational Codeforces Round 60 (Rated for Div. 2) 题解
Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...
随机推荐
- DataGrip连接MySql数据库失败:dataGrip java.net.ConnectException: Connection refused: connect.
1.问题 报错:dataGrip java.net.ConnectException: Connection refused: connect. 详细错误:[08S01] Communications ...
- 如何使用Oracle Enterprise Manager Database Express连接到PDB数据库
1.问题 1.1重复弹出登录框,无法登陆 关闭登录框,显示invalid container name 1.2 重启后PDB数据库处于mounted挂载状态,未打开导致使用 Enterprise 登陆 ...
- 在Winform系统开发中,使用MediatR来实现类似事件总线的消息处理
MediatR是一款进程内的消息订阅.发布框架,可实现请求/响应.命令.查询.通知和事件的消息传递,解耦了消息处理器和消息之间耦合.提供了Send方法用于发布到单个处理程序.Publish方法发布到多 ...
- [转帖]Oracle 性能优化 之 游标及 SQL
https://www.cnblogs.com/augus007/articles/9273236.html 一.游标 我们要先说一下游标这个概念. 从 Oracle 数据库管理员的角度上说,游标是对 ...
- TiDB恢复部分表的方式方法
TiDB恢复部分表的方式方法 背景 今天同事告知误删了部分表. 因为是UAT准生产的环境, 所以仅有每天晚上11点的备份处理. 同时告知 昨天的数据也可以. 得到认可后进行了 TiDB的单表备份恢复. ...
- [转帖]FIO磁盘性能测试工具
https://www.cnblogs.com/lyhabc/p/16708771.html 简介 一般我们测试硬盘或者存储的性能的时候,会用Linux系统自带的dd命令,因为是自带命令,简单易使用, ...
- [转帖]python字符串如何删除后几位
https://www.python51.com/jc/15070.html 1.首先在jupyter notebook中新建一个空白的python文件: 2.然后定义一个字符串,用字符串截取的方式打 ...
- 解决Word等打开嵌入的文件提示 包含有害内容 无法打开的问题
最近打开文件时提示: 从网上找了一下 最简单的解决办法是: 新建一个文件, 输入如下内容 导入注册表 每次打开时不进行 文件有效性的检查即可. 为了省事 我多加了几个版本的 如果是excel 将 w ...
- 万能shell 简单查看已存在日志所有的启动记录
程序将日志 自动打包成了 gz 文件, 今天突然想查查所有的日志有没有相关关键字. 第一步解压缩所有的日志 cd 到相关目录 for i in `ls` ; do gzip -d $i ; done ...
- 数组查询includes
let arr1 = ['kk', 'jo', 'll']; if (arr1.includes("kk")) {//[ɪnˈkluːz] console.log("找到 ...