Codeforces Round #704 (Div. 2)(A ~ E)5题全 超高质量题解【每日亿题2 / 23】
整理的算法模板合集: ACM模板
点我看算法全家桶系列!!!
实际上是一个全新的精炼模板整合计划
目录
- A、Three swimmers
- B、Card Deck
- C、Maximum width
- D、Genius's Gambit
- E、Almost Fault-Tolerant Database
好耶,好多人 AK 诶
究极上分场
下午有事题解更晚了…
A、Three swimmers
Problem
三个人游泳,第一个人游一圈花费 aaa ,第二个人 bbb ,第三个人 ccc ,他们会一圈一圈地游,即第一个人在 0,a,2a,3a⋯0,a,2a,3a\cdots0,a,2a,3a⋯ 的时间在左边,第二第三个同理。
你在时间 ppp 到达游泳池左边,问见到第一个人你需要等待的时间是多少?
Solution
签到题 ~
首先如果 aOR bOR ca \ \text{OR}\ b \ \text{OR}\ ca OR b OR c 是 ppp 的约数,那么我一到游泳池就能见到一位,等待的时间为 000。
否则我就需要等他们游过来,也就是 ppp 时刻对于第一个人来说,已经游了 p%ap\ \%\ ap % a 的时间,因为 % 运算就是得到余数,实际意义就是 aaa 的倍数离 ppp 差多少,所以还需要再等 a−p%aa-p\ \%\ aa−p % a 的时间。三个人取最小值即可。
Code
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;
typedef long long ll;
typedef int itn;
const int N = 2e4 + 7;
const ll INF = 4e18;int n, m, t;
ll a, b, c, p;void solve()
{scanf("%lld%lld%lld%lld", &p, &a, &b, &c);if(p % a == 0 || p % b == 0 || p % c == 0) {puts("0");}else {ll ans = INF;ans = min({a - p % a, b - p % b, c - p % c});printf("%lld\n", ans);}
}int main()
{scanf("%d", &t);while(t -- ) {solve();}
}
B、Card Deck
Problem
给你一副 nnn 张的扑克牌,你想要重排它。
输入长度为 nnn 的数组 ppp,编号为 1∼n1\sim n1∼n 的扑克牌,第 iii 张权值为 pip_ipi,且 pip_ipi 不会重复。扑克牌按照编号顺序从底向上放,也就是 p1p_1p1 在最下面, pnp_npn 在最上面 。
每次你可以选择一个整数 k>0k>0k>0 ,从原堆牌顶拿走 kkk 张放到新堆的顶部,直到原堆的牌空了。
大概就是这个样子:
5
4 3
3 3 2
2 -> 2 + 5 -> 2 + 5
1 1 4 1 4
定义一副牌的 orderorderorder 为 ∑i=1nnn−i⋅pi\sum\limits_{i = 1}^{n}{n^{n - i} \cdot p_i}i=1∑nnn−i⋅pi。
给定原序列,求可以通过操作得到的最大的 orderorderorder 。
Solution
签到题 ~
根据这个权值公式, ∑i=1nnn−i⋅pi\sum\limits_{i = 1}^{n}{n^{n - i} \cdot p_i}i=1∑nnn−i⋅pi ,手玩几组样例,发现最大的放到最前面一定是最优的,因为最前面是乘上 nnn^nnn。然后题目中放一次,必须是放一整段,也就是从权值最大的牌一直到最右边全部摞到新堆上,所以我们放完这一段之后再找剩下牌中最大的即可。怎么找最大的呢,因为权值有且只有 1∼n1\sim n1∼n,并且最关键在于权值没有重复,所以我们只需要开一个桶存一下权值的下标,从大到小枚举找一下双指针划定范围即可。如果有重复的话可以用 ST 表 / 线段树处理一下区间最大值即可。
Code
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;
typedef int ll;
typedef int itn;
const int N = 2e5 + 7;
const ll INF = 2e9;int n, m, t;
ll a[N], b[N];
ll vis[N];int main()
{scanf("%d", &t);while(t -- ) {scanf("%d", &n);for(int i = 1; i <= n; ++ i) {scanf("%d", &a[i]);vis[a[i]] = i;}ll last = n + 1;for(int i = n; i >= 1; -- i) {for(int j = vis[i]; j <= last - 1; ++ j) {printf("%d ", a[j]);}last = min(last, vis[i]);}puts("");}return 0;
}
C、Maximum width
Problem
给定两个字符串,s,ts,ts,t,长度分别为nnn 和 mmm,请你在 sss 中选择一个子序列等于 ttt,定义所有等于 ttt 的子序列的宽度为子序列相邻两字母下标差值的最大值。请你找到最大的宽度。
Solution
签到题 ~
因为 sss 中一定存在子序列等于 ttt ,我们要找的是下标最大的差值,所以很明显我们可以双指针分别对正序扫描 sss ,逆序扫描 ttt ,找到所有字符的第一个相匹配的位置,存一下下标即可,正确性显然,预处理完之后,相邻的减一下取最大值即可。
Code
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;
typedef long long ll;
typedef int itn;
const int N = 2e5 + 7;
const ll INF = 4e18;int n, m;int pre[N], suf[N];
char s[N], t[N];void solve()
{scanf("%d%d%s%s", &n, &m, s + 1, t + 1);for(int i = 1, j = 1; i <= n; ++ i) {if(s[i] == t[j]) {pre[j] = i;j ++ ;}if(j > m) break;}for(int i = n, j = m; i >= 1; -- i) {if(s[i] == t[j]) {suf[j] = i;j -- ;}if(j == 0) break;}int ans = 0;for(int i = 1; i < m; ++ i) {ans = max(ans, suf[i + 1] - pre[i]);}printf("%d\n", ans);
}int main()
{solve();return 0;
}
D、Genius’s Gambit
Problem
给定三个整数 a,b,ka,b,ka,b,k,找到两个二进制数 x,yx,yx,y (x>yx>yx>y),满足 xxx 和 yyy 都包含 aaa 个 000 和 bbb 个 111 。且 x−yx-yx−y 恰好有 kkk 个 111 。要求 x,yx,yx,y 没有前导零。
Solution
先简单讲一下吧,明天再细说
就是我们手算发现
1 0
0 1⬇
0 1
1 0 0
0 0 1⬇
0 1 1
1 0 0 0
0 0 0 1⬇
0 1 1 1
也就是我们长度为 xxx ,最多能减出来 x−1x-1x−1 个 111。
而多出来的 111 我们将他们对应放置就可以直接剪掉了。
因为不能有前导零,所以前两个一定是 111 ,也就是说我们本来一共有 a+ba+ba+b 个,但是前两个要是 111 ,少了一个贡献,也就是说只有 a+b−1a+b-1a+b−1 的长度可以任由我们摆布(bushi),我们就可以摆成上述情况,也就是最多能组成 a+b−2a+b-2a+b−2 个 111 ,所以如果 k>a+b−2k>a+b-2k>a+b−2 就直接输出 NoNoNo 即可。
当 k=0k=0k=0 时,显然我们让 111 和 111 对应即可。
当 k>a+b−2k>a+b-2k>a+b−2 时,无解 输出 NoNoNo。
当 a<0a<0a<0 或者 b<2b<2b<2 时,只有 k=0k=0k=0 才可以凑出来,否则就是 NoNoNo。
剩余的情况,我们就按照上述方法凑出 k+1k+1k+1 的区间,其余多出来的 111 让它减掉就好。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;
typedef long long ll;
typedef int itn;
const int N = 2e5 + 7;int n, m, t, k;
int a, b, k1, k2;
itn sum[N];void solve()
{scanf("%d%d%d", &a, &b, &k);if(k == 0) {puts("Yes");for(int i = 1; i <= b; ++ i) {printf("1");}for(int i = 1; i <= a; ++ i) {printf("0");}puts("");for(int i = 1; i <= b; ++ i) {printf("1");}for(int i = 1; i <= a; ++ i) {printf("0");}puts("");}else if(a == 0 || b == 1 || b == 0) {puts("No");}else if(k > a + b - 2) {puts("No");}else {puts("Yes");printf("11");string ans1 = " ";for(int i = 1; i < a; ++ i) {ans1 += "0";}for(int i = 1; i < b - 1; ++ i) {ans1 += "1";}for(int i = 1; i <= k - 1; ++ i)putchar(ans1[i]);printf("0");for(int i = k; i < a + b - 2; ++ i)putchar(ans1[i]);puts("");printf("10");string ans2 = " ";for(int i = 1; i < a; ++ i) {ans2 += "0";}for(int i = 1; i < b - 1; ++ i) {ans2 += "1";}for(int i = 1; i <= k - 1; ++ i)putchar(ans2[i]);printf("1");for(int i = k; i < a + b - 2; ++ i)putchar(ans2[i]);puts("");}
}int main()
{solve();return 0;
}
E、Almost Fault-Tolerant Database
Problem
给定 nnn 个长度为 mmm 的数组,你需要输出一个长度为 mmm 的数组,使得这 n+1n+1n+1 个数组之间不同的数不超过两个,输出 YesYesYes,输出你构造的数组,若有多种情况,可任意输出一种。如若不存在,输出 NoNoNo 。
Solution
Codeforces Round #704 (Div. 2)(A ~ E)5题全 超高质量题解【每日亿题2 / 23】相关推荐
- Codeforces Round #704 (Div. 2)-A. Three swimmers-题解
目录 Codeforces Round #704 (Div. 2)-A. Three swimmers Problem Description Input Output Sample Input Sa ...
- Codeforces Round #704 (Div. 2)-C. Maximum width-题解
目录 Codeforces Round #704 (Div. 2)-C. Maximum width Problem Description Input Output Sample Input Sam ...
- Codeforces Round #704 (Div. 2)-B. Card Deck-题解
目录 Codeforces Round #704 (Div. 2)-B. Card Deck Problem Description Input Output Sample Input Sample ...
- Codeforces Round #588 (Div. 2) F. Konrad and Company Evaluation 图论 + 建反图 好题
传送门 文章目录 题意: 思路: 题意: 给你一张nnn个点mmm条边的图,其中每个点iii初始编号为iii,边是有向的,方向为从编号大的指向编号小的.定义一个贡献为存在某三个点a,b,ca,b,ca ...
- Codeforces Round #704 (Div. 2) E. Almost Fault-Tolerant Database 思维
传送门 题意: 给nnn个长度为mmm的数组,要求构造一个长度为mmm的数组,使得这个数组与前面nnn个数组同一位置最多两个元素不同. 思路: 我们为了方便构造,可以先把要构造的数组看成nnn个数组的 ...
- Codeforces Round #704 (Div. 2) D. Genius‘s Gambit 构造 + 细节
传送门 题意: 给a,b,ka,b,ka,b,k,要求用aaa个000和bbb个111组成二进制xxx和yyy,并且x−yx-yx−y恰好有kkk个111,并且xxx和yyy不含前导零. 思路: 首先 ...
- Codeforces Round #704 (Div. 2) A-E题解
A Three swimmers 题意 三个人每人游一个来回时间分别是a.b.c,那么在 a.b.c的倍数时间点上 三个人均会在左边的点,题目问你p时刻来 还要等多久最快遇到三个人 1e18 除法判断 ...
- Codeforces Round #493 (Div. 2) C. Convert to Ones 乱搞_构造_好题
题意: 给你一个长度为 nnn 的 010101串 ,你有两种操作: 1.将一个子串翻转,花费 XXX 2.将一个子串中的0变成1,1变成0,花费 YYY 求你将这个01串变成全是1的串的最少花费. ...
- Codeforces Round #637 (Div. 2) - Thanks, Ivan Belonogov! D. Nastya and Scoreboard题解(记忆化搜索)
题目链接 题目大意 一个n个数码位的分数板,每一个数码位都是一个七段数码管,现在给出每个数码位的显示情况,问再点亮k段数码管的话能显示的最大的数是多少,如果不能构成一串数字,就输出-1.答案允许有前导 ...
最新文章
- Java架构演进之路
- jdk1.8中接口可以写默认方法
- java 里如何实现逻辑返回值_☆技术问答集锦(五)
- Linux重启网卡的方法
- mui 头部tab代码
- 面向对象程序设计要考虑的7个原则
- js数组查找最接近_如何从javascript中的对象数组中获取最接近的先前id
- Pass4side EMC E20-817认证考试题库
- 08. 旋转数组的最小数字(C++版本)
- 随身助手271个可用api接口网站php源码(随身助手API)
- python activex_如何在python中使用ActiveX控件
- 计算机硬件主板各部分内部结构,电脑主板各个模块介绍与原理解读
- 组策略设置计算机计划任务,使用组策略配置域中任务计划
- 自定义系统右键菜单工具-使用说明
- windows安装配置jdk1.8
- code3:使用set判断数组中是否有重复值
- 飞机大战4-我的子弹
- PS图层+移动工具(2)复制删除快捷键 图层分组 前景色填充
- The requested URL returned error: 403
- hive查看一张表的分区字段_Hive表分区与索引
热门文章
- 技巧 | OpenCV程序执行时间计算
- 【项目实践】车距+车辆+车道线+行人检测项目实践
- 图像配准的前世今生:从人工设计特征到深度学习
- IntelliJ IDEA 最常用配置,应用、永久激活
- Installing Oracle Database 18c Using RPM Packages
- scroll-苹果滑动卡顿
- 分布式事物-2pc和3pc区别
- 《Typecript 入门教程》 2、访问控制符:public、private、protected、readonly
- String.fromCharCode()
- 馅饼还是陷阱,TMG2010升级经验谈