整理的算法模板合集: 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∑n​nn−i⋅pi​。

给定原序列,求可以通过操作得到的最大的 orderorderorder 。

Solution

签到题 ~

根据这个权值公式, ∑i=1nnn−i⋅pi\sum\limits_{i = 1}^{n}{n^{n - i} \cdot p_i}i=1∑n​nn−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】相关推荐

  1. Codeforces Round #704 (Div. 2)-A. Three swimmers-题解

    目录 Codeforces Round #704 (Div. 2)-A. Three swimmers Problem Description Input Output Sample Input Sa ...

  2. Codeforces Round #704 (Div. 2)-C. Maximum width-题解

    目录 Codeforces Round #704 (Div. 2)-C. Maximum width Problem Description Input Output Sample Input Sam ...

  3. Codeforces Round #704 (Div. 2)-B. Card Deck-题解

    目录 Codeforces Round #704 (Div. 2)-B. Card Deck Problem Description Input Output Sample Input Sample ...

  4. Codeforces Round #588 (Div. 2) F. Konrad and Company Evaluation 图论 + 建反图 好题

    传送门 文章目录 题意: 思路: 题意: 给你一张nnn个点mmm条边的图,其中每个点iii初始编号为iii,边是有向的,方向为从编号大的指向编号小的.定义一个贡献为存在某三个点a,b,ca,b,ca ...

  5. Codeforces Round #704 (Div. 2) E. Almost Fault-Tolerant Database 思维

    传送门 题意: 给nnn个长度为mmm的数组,要求构造一个长度为mmm的数组,使得这个数组与前面nnn个数组同一位置最多两个元素不同. 思路: 我们为了方便构造,可以先把要构造的数组看成nnn个数组的 ...

  6. 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不含前导零. 思路: 首先 ...

  7. Codeforces Round #704 (Div. 2) A-E题解

    A Three swimmers 题意 三个人每人游一个来回时间分别是a.b.c,那么在 a.b.c的倍数时间点上 三个人均会在左边的点,题目问你p时刻来 还要等多久最快遇到三个人 1e18 除法判断 ...

  8. Codeforces Round #493 (Div. 2) C. Convert to Ones 乱搞_构造_好题

    题意: 给你一个长度为 nnn 的 010101串 ,你有两种操作: 1.将一个子串翻转,花费 XXX 2.将一个子串中的0变成1,1变成0,花费 YYY 求你将这个01串变成全是1的串的最少花费. ...

  9. Codeforces Round #637 (Div. 2) - Thanks, Ivan Belonogov! D. Nastya and Scoreboard题解(记忆化搜索)

    题目链接 题目大意 一个n个数码位的分数板,每一个数码位都是一个七段数码管,现在给出每个数码位的显示情况,问再点亮k段数码管的话能显示的最大的数是多少,如果不能构成一串数字,就输出-1.答案允许有前导 ...

最新文章

  1. Java架构演进之路
  2. jdk1.8中接口可以写默认方法
  3. java 里如何实现逻辑返回值_☆技术问答集锦(五)
  4. Linux重启网卡的方法
  5. mui 头部tab代码
  6. 面向对象程序设计要考虑的7个原则
  7. js数组查找最接近_如何从javascript中的对象数组中获取最接近的先前id
  8. Pass4side EMC E20-817认证考试题库
  9. 08. 旋转数组的最小数字(C++版本)
  10. 随身助手271个可用api接口网站php源码(随身助手API)
  11. python activex_如何在python中使用ActiveX控件
  12. 计算机硬件主板各部分内部结构,电脑主板各个模块介绍与原理解读
  13. 组策略设置计算机计划任务,使用组策略配置域中任务计划
  14. 自定义系统右键菜单工具-使用说明
  15. windows安装配置jdk1.8
  16. code3:使用set判断数组中是否有重复值
  17. 飞机大战4-我的子弹
  18. PS图层+移动工具(2)复制删除快捷键 图层分组 前景色填充
  19. The requested URL returned error: 403
  20. hive查看一张表的分区字段_Hive表分区与索引

热门文章

  1. 技巧 | OpenCV程序执行时间计算
  2. 【项目实践】车距+车辆+车道线+行人检测项目实践
  3. 图像配准的前世今生:从人工设计特征到深度学习
  4. IntelliJ IDEA 最常用配置,应用、永久激活
  5. Installing Oracle Database 18c Using RPM Packages
  6. scroll-苹果滑动卡顿
  7. 分布式事物-2pc和3pc区别
  8. 《Typecript 入门教程》 2、访问控制符:public、private、protected、readonly
  9. String.fromCharCode()
  10. 馅饼还是陷阱,TMG2010升级经验谈