Codeforces Round #821 (Div. 2) A-E
A
题解
知识点:贪心。
下标模 \(k\) 相同分为一组,共有 \(k\) 组,组间不能互换,组内任意互换。
题目要求连续 \(k\) 个数字,一定能包括所有的 \(k\) 组,现在只要在每组中选取最大的加在一起即可。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[107];
bool solve() {
int n, k;
cin >> n >> k;
for (int i = 1;i <= n;i++) cin >> a[i];
ll ans = 0;
for (int i = 1;i <= k;i++) {
int mx = 0;
for (int j = i;j <= n;j += k)
mx = max(mx, a[j]);
ans += mx;
}
cout << ans << '\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
题解
知识点:构造。
注意到,必然会有人赢 \(0\) 次,有人会赢非 \(0\) 次,因此 \(x, y = 0\) 或者 \(x,y \neq 0\) 都是不存在的。
假设非 \(0\) 数为 \(x\) ,即赢的人都赢 \(x\) 次,其他人都直接输掉,因为共有 \(n-1\) 次机会,那么只有 \(x | n-1\) 时合法,其余情况不存在。
在合法的情况下,尝试构造。我们只需要确定第一场赢的人,然后每隔 \(x\) 场换个人即可。为了方便,我们确定 \(2\) 为第一场赢的人,这样我们对人的编号加 \(x\) 就是下一个人。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool solve() {
int n, x, y;
cin >> n >> x >> y;
if (x && y || !x && !y) return false;
if (x < y) swap(x, y);
if ((n - 1) % x) return false;
else {
for (int i = 2;i <= n;i += x) {
for (int j = 1;j <= x;j++)
cout << 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;
}
C
题解
知识点:构造。
考虑通过 \(n-1\) 次操作使得序列元素全部相等。
注意到同奇同偶和为偶数使数字向左转移,否则为奇数使数字向右转移。
显然,可以通过第一个数字把右侧所有与之奇偶性不同的数字变成相等的,现在考虑与第一个数字奇偶性相同的数字相等。
因为同奇偶性,所以只能向左转移。考虑找到最后一个与第一个数字同奇偶性的数字,随后通过这个数字向左把同奇偶性的数字都变为相等,之后再执行上一步把不同奇偶性的数字变成相等的。
上述操作,每次都能增加一个与初始数字确定相等的数字,所以共操作 \(n-1\) 次。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool vis[100007];
bool solve() {
int n;
cin >> n;
int ls = 1;
for (int i = 1, x;i <= n;i++) {
cin >> x;
vis[i] = x & 1;
if (vis[1] == vis[i]) ls = i;
}
cout << n - 1 << '\n';
for (int i = ls - 1;i >= 1;i--) {
if (vis[i] == vis[1])
cout << i << ' ' << ls << '\n';
}
for (int i = 2;i <= n;i++) {
if (vis[1] != vis[i])
cout << 1 << ' ' << i << '\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
题解
知识点:区间dp,贪心。
任何时候,如果需要修改的地方是奇数,则不存在解法,即 \(-1\) 情况。
简单版本,规定 \(x \geq y\) ,因此:
- 当需要修改的位置 \(cnt\geq 4\) 时,可以每次隔一个取,使花费永远是 \(y\) ,最终花费是 \(\dfrac{cnt}{2} \cdot y\) 。
- 当 \(cnt = 2\) 时,除了花费 \(x\) 直接消掉,还可以通过一个其他不相邻的位置中转,两次不相邻修改实现一次相邻修改,花费 \(2y\) ,因此总花费是 \(\min(x,2y)\) 。
困难版本,没有规定 \(x,y\) 关系,但 \(x \geq y\) 那部分可以直接用贪心结论解决,\(x < y\) 只能dp解决了,这里采用线性dp,其他dp也能做。
设 \(dp[i]\) 表示从 \(1\) 到 \(i\) 修改成一样的最小花费。
当 \(i\) 为偶数时,\(dp[i] = \min(dp[i - 2] + (v[i] - v[i - 1]) \cdot x, dp[i - 1] + y)\) :
- 修改了前 \(i-2\) 个位置的花费,加上链式 \(x\) 修改第 \(i-1\) 和 \(i\) 个的花费。
- 修改了前 \(i-1\) 个位置除了一个位置没修改(可能在任何位置,也即包括了在第 \(i-1\) 处)的花费,加上不相邻修改 \(y\) 的花费。
取最小值。其中前者修改不需要考虑 \(y\) ,因为后者包括了;后者不需要考虑 \(x\) 链式修改,可以证明不可能更优。
当 \(i\) 为奇数时,\(dp[i] = \min(dp[i - 2] + (v[i] - v[i - 1]) \cdot x, dp[i - 1])\) :
- 修改了前 \(i-2\) 个位置除了一个位置没修改的花费,加上链式 \(x\) 修改第 \(i-1\) 和 \(i\) 个的花费。
- 修改了前 \(i-1\) 个位置的花费,留下第 \(i\) 处没修改。
取最小值。其中前者修改不需要考虑 \(y\) 不相邻修改,因为前者如果使用 \(y\) 修改 \(i-1\) 和 \(i\),花费等价于 \(dp[i-1]\) 的情况之一,即 \(dp[i-2]+y \geq dp[i-1]\) ,后者更优在于保留了第 \(i\) 个位置而非更前的位置,对偶数情况有更好的影响。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[5007];
bool solve() {
int n;
ll x, y;
string a, b;
vector<int> v;
cin >> n >> x >> y;
cin >> a >> b;
v.clear();
for (int i = 0;i < n;i++) {
if (a[i] != b[i]) v.push_back(i);
}
if (v.size() & 1) return false;
if (!v.size()) {
cout << 0 << '\n';
return true;
}
if (x >= y) {
if (v.size() == 2 && v.front() + 1 == v.back()) cout << min(x, 2 * y) << '\n';
else cout << v.size() / 2LL * y << '\n';
}
else {
dp[0] = 0;
dp[1] = min((v[1] - v[0]) * x, y);
for (int i = 2;i < v.size();i++) {
if (i & 1) dp[i] = min(dp[i - 2] + (v[i] - v[i - 1]) * x, dp[i - 1] + y);
else dp[i] = min(dp[i - 2] + (v[i] - v[i - 1]) * x, dp[i - 1]);
}
cout << dp[v.size() - 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;
}
E
题解
知识点:数学,线性dp。
显然,直接求第 \(t\) 秒 \((x,y)\) 是否有球非常困难,但是求 \([0,t]\) 秒内经过 \((x,y)\) 的数量(包括这个格子本身)是比较容易的。
每个位置都是方向右下交替进行,且初始是朝右。因此,假设 \([0,t]\) 秒内经过 \((i,j)\) 的球有 \(n\) 个,那么可以得知 \([0,t+1]\) 秒内经过 \((i+1,j)\) 的球有 \(\lceil \frac{n}{2} \rceil\) 个,经过 \((i,j+1)\) 的球有 \(\lfloor \frac{n}{2} \rfloor\) 个。
但是,在 \(t+1\) 秒及其之后到达 \((i,j)\) 的球不可能在 \([0,t+1]\) 秒内经过 \((i+1,j)\) 和 \((i,j+1)\) ,因为从 \((i,j)\) 到 \((i+1,j)\) 或 \((i,j+1)\) 需要 \(1\) 秒。因此,要求 \([0,t]\) 秒内经过 \((x,y)\) 的数量,则只需要 \([0,t-(i+j)]\) 秒内经过 \((i,j)\) 的数量。
我们知道 \([0,t]\) 内经过 \((0,0)\) 的球有 \(t+1\) 个。因此,能递推得出 \([0,t]\) 秒内经过 \((x,y)\) 的球的个数。。
设 \(dp[i][j]\) 是 \([0,t]\) 秒内 \((i,j)\) 经过了多少能到达 \((x,y)\) 的球的数量,初始条件是 \(dp[0][0] = \min(t - (x+y)+1,0)\) 。转移方程为:
dp[i + 1][j] += dp[i][j] / 2;
dp[i][j + 1] += dp[i][j] - dp[i + 1][j];
时间复杂度 \(O(q)\)
空间复杂度 \(O(1)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll get(ll t, int x, int y) {
vector<vector<ll>> dp(x + 7, vector<ll>(y + 7));
dp[0][0] = max(t - (x + y) + 1, 0LL);
for (int i = 0;i <= x;i++) {
for (int j = 0;j <= y;j++) {
dp[i + 1][j] += dp[i][j] / 2;
dp[i][j + 1] += dp[i][j] - dp[i + 1][j];
}
}
return dp[x][y];
}
bool solve() {
ll t;
int x, y;
cin >> t >> x >> y;
cout << (get(t, x, y) - get(t - 1, x, y) ? "YES" : "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;
}
Codeforces Round #821 (Div. 2) A-E的更多相关文章
- Codeforces Round #821(Div.2) (A-C) 题解
Codeforces Round #821(Div.2) (A-C) A.Consecutive Sum 大致题意 给定一组共 n 个数据 ,如果俩个数的下标在 mod k 意义下同余,则可以交换a[ ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
- Codeforces Round #368 (Div. 2)
直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- Codeforces Round #279 (Div. 2) ABCDE
Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name A Team Olympiad standard input/outpu ...
- Codeforces Round #262 (Div. 2) 1003
Codeforces Round #262 (Div. 2) 1003 C. Present time limit per test 2 seconds memory limit per test 2 ...
- Codeforces Round #262 (Div. 2) 1004
Codeforces Round #262 (Div. 2) 1004 D. Little Victor and Set time limit per test 1 second memory lim ...
- Codeforces Round #371 (Div. 1)
A: 题目大意: 在一个multiset中要求支持3种操作: 1.增加一个数 2.删去一个数 3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给 ...
- Codeforces Round #268 (Div. 2) ABCD
CF469 Codeforces Round #268 (Div. 2) http://codeforces.com/contest/469 开学了,时间少,水题就不写题解了,不水的题也不写这么详细了 ...
随机推荐
- mysql too many connections 解决
本文为博主原创,转载请注明出处: 由于在开发过程中,很多人连接共同一个数据库,在工具连接到mysql, 并执行sql时,提示 too many connections ,这是由于数据库连接太多,以致于 ...
- C++ 语法结构--堆
1.堆介绍 「堆 heap」是一种满足特定条件的完全二叉树,主要可分为图 8-1 所示的两种类型. 「大顶堆 max heap」:任意节点的值 其子节点的值. 「小顶堆 min heap」:任意节点的 ...
- MPC 是下一代私钥安全的7大原因
PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全.密码学.联邦学习.同态加密等隐私计算领域的技术和内容. 多重签名钱包与单一密钥钱包相比,因其提升了资产安全性,如今已成为 ...
- 为什么 sort() 中的 return a-b 可以决定升序
arr.sort( function(a,b){ return a-b; } ) 千万不要理解成 a 减 b 其实它代表的是26个字母中的 a 和 b b 比 a 大,所以 a - b 就是升序,写成 ...
- 【Mysql系列】(一)MySQL语句执行流程
首发博客地址 首发博客地址 系列文章地址 参考文章 MySQL 逻辑架构 连接器 连接命令一般是这么写的 mysql -h$ip -P$port -u$user -p 那么 什么是连接器? MySQL ...
- [转帖]【sql server安全】sql server连接加密,sql server SSL加密连接
https://www.cnblogs.com/gered/p/13595098.html#_label1_0 MSSQL - 最佳实践 - 使用SSL加密连接 回到顶部 author: 风移 回到顶 ...
- [转帖]CentOS8时间同步服务
时间同步服务 CentOS7之前的版本用的是ntpdate服务,之后用的是chrony服务 默认是安装的了 查看版本 [root@centos8 ~]#rpm -qi chrony Name : ch ...
- [转帖]Kafka 核心技术与实战学习笔记(七)kafka集群参数配置(上)
一.Broker 端参数 Broke存储信息配置 log.dirs:非常重要,指定Broker需要使用的若干文件目录路径,没有默认值必须亲自指定. log.dir:他只能表示单个路径,补充上一个参数用 ...
- [转帖]sendfile“零拷贝”、mmap内存映射、DMA
https://www.jianshu.com/p/7863667d5fa7 KAFKA推送消息用到了sendfile,落盘技术用到了mmap,DMA贯穿其中. 先说说零拷贝 零拷贝并不是不需要拷贝, ...
- open,os模块的常用函数
一.open用于读写文件 1.open的基本语法 : open(file,mode,buffering,encoding,errors.........),open中有如下几个参数,一般情况 下我们只 ...