整理的算法模板合集: 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. 使用Spring Security的多租户应用程序的无状态会话
  2. 各类手机开发平台介绍(转载)
  3. Spring→面向切面编程AOP、相关概念、通知Advice类型、配置切面切入点通知、AOP相关API、AOP代理类ProxyFactoryBean、AOP注解@AspectJ
  4. toad 连接mysql8.0_toad for mysql免费版
  5. Arduino开发板使用DS3231实时时钟模块的方法
  6. 代码开源为黑客敞开了大门
  7. linux查看照片命令,php 及 linux 命令行方式读取 图片 exif 信息
  8. Pigeon中的流量限制
  9. UE4 Slate二 用UMG思想去理解Slate+Slate编码
  10. 免费素材:气球样式的图标集(PSD, SVG, PNG)
  11. git报错:error: failed to push some refs to ... 的解决办法及如何让线上覆盖本地方法【Git/SVN】
  12. 用智能ABC关闭程序
  13. Vert.x(vertx) 创建HTTP服务
  14. bzoj3785--骑士游戏--有“环”的动态规划
  15. 狄拉克函数及其基本性质
  16. QQ音乐播放器-jQuery实现
  17. 如何做一个手机产品标签
  18. (十) 深度学习笔记 | 关于优化器Adam
  19. list申请java,java把一个list中的内容添加到另一个list中 FPGA编程问题:有多个.v文件与module,把他们加到......
  20. 加密算法之MD5算法

热门文章

  1. Python 200个标准库汇总
  2. 一个有趣的案例 | 页面扭曲矫正
  3. 基于OpenCV实战的图像处理:色度分割
  4. Multisim 12.0 笔记
  5. linux的那些破事
  6. SpringMVC基础及应用-李守红
  7. MySQL解压版配置
  8. 用shell解决ddos攻击实例
  9. 《转载》Java异常处理的10个最佳实践
  10. nagios 数据库管理之 NDOUtils