整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解

比赛链接:https://codeforces.com/contest/1474

  • A. 贪心
  • B. 数论
  • C. 思维
  • D. 思维
  • E. 构造
  • F. DP + 矩阵快速幂

目录

  • Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解
  • A. Puzzle From the Future
  • B. Different Divisors
  • C. Array Destruction
  • D. Cleaning
  • E. What Is It?
  • F. 1 2 3 4 ...

A. Puzzle From the Future

Problem

对于两个长度为 nnn 的二进制整数 aaa,bbb ,通过以下方式构造出整数 ddd:

将 aaa 和 bbb 按位相加但不进行进位运算,得到一个整数 ccc,因此 ccc 中可能有 222 。例如将 011001100110 与 110111011101 按位相加的结果是 121112111211。

将 ccc 中相同且连续的数字替换为一位,得到 ddd。例如将 022000022000022000 变成 020020020(因此,ddd 没有相同且连续的数字)。

现在,给你 bbb,求一个 aaa 使得 ddd 最大。

1≤t≤1000,1≤n≤1051 \leq t \leq 1000,1 \leq n \leq 10^51≤t≤1000,1≤n≤105

Solution

非常简单的按位贪心

数尽量地大,就是最高位直接置为 111 ,然后后面也是尽可能地越大越好,并且因为如果有连续的 111 或者连续的 000 就会消掉,会更亏,所以要避免这种情况,我们就标记一下上一个是 000 还是 111 还是 222 ,下一个就要避免掉这种情况,简单在纸上写一下四种情况,然后模拟一下即可。

// Problem: A. Puzzle From the Future
// Contest: Codeforces - Codeforces Round #696 (Div. 2)
// URL: https://codeforces.com/contest/1474/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;const int N = 50007;int n, m, t;
string a, b;int main()
{scanf("%d", &t);while(t -- ) {scanf("%d", &n);cin >> b;string a = "";a += '1';int last = 1 + b[0] - '0';for(int i = 1; i < b.length(); ++ i) {if(last == 2) {if(b[i] == '1')a += '0';else a += '1';}else if(last == 1) {if(b[i] == '1')a += '1';else a += '0';}else a += '1';last = a[i] - '0' + b[i] - '0';}cout << a << endl;}return 0;
}

B. Different Divisors

Problem

给定正整数 d(d≤104)d(d\le 10^{4})d(d≤104),请求出最小的满足如下条件的正整数 aaa:

  • aaa 至少有四个正因子(111 和它本身计算在内)
  • 对于 aaa 的任两个正因子 x,y(x<y)x,y(x<y)x,y(x<y),y−x≥dy-x\ge dy−x≥d

1≤t≤3000,1≤d≤100001 \leq t \leq 3000,1 \leq d \leq 100001≤t≤3000,1≤d≤10000

Solution

首先就是至少有四个因子嘛,除去 111 和它本身,就只剩下两个因子 x,yx,yx,y 满足: 1,x,y,x×y1,x,y,x\times y1,x,y,x×y。a=x×ya=x\times ya=x×y

有一种感觉就是因子越少数越小。两个因子 x,yx,yx,y ,并且只有这两个因子,很明显就是两个素数,所以我们先筛一下素数,因为 ddd 只有 10410^4104 ,保守估计我们最多需要筛到 10510^5105大概,所以我们筛到 10710^7107 好啦 ~

然后还有一个要求就是因子差必须大于等于 ddd,也就是先找到第一个大于 ddd 的素数 xxx(或者说 x≥d+1x\ge d+1x≥d+1,因为从 111 开始),然后再找到第一个大于等于 x+dx+dx+d 素数,把他们乘起来就是要求的整数 aaa 。这一系列操作很明显可以用二分实现,因为数据很小,甚至暴力找也行…

然后简单地实现一下就行了 ~

Code

// Problem: B. Different Divisors
// Contest: Codeforces - Codeforces Round #696 (Div. 2)
// URL: https://codeforces.com/contest/1474/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
const int N = 5e7 + 7, mod = 1e9 + 7;
typedef long long ll;int n, m, q, d;
int t;ll a1, a2, b1, b2, c1, c2;int primes[N];
bool vis[N];
int cnt;void get_primes(int n)
{for(int i = 2; i <= n; ++ i) {if(vis[i] == 0) primes[ ++ cnt] = i;for(int j = 1; j <= cnt && primes[j] * i <= n; ++ j) {vis[i * primes[j]] = true;if(i % primes[j] == 0) break;}}
}int main()
{scanf("%d", &t);get_primes(N - 1);while(t -- ) {scanf("%d", &d);int id = upper_bound(primes + 1, primes + 1 + cnt, d) - primes;int a = primes[id];id = lower_bound(primes + 1, primes + 1 + cnt, a + d) - primes;int b = primes[id];printf("%d\n", a * b);}return 0;
}

C. Array Destruction

Problem

你有一个长度为 2n2n2n 的无用数组 aaa ,现在要进行一些操作将数组的所有元素清除:

  1. 选择一个正整数 xxx。
  2. 选择 aaa 数组的任意两个数使得它们的和等于 xxx,并将这两个数从 aaa 数组中删除。
  3. 将 xxx 更改为选择的两个数的最大值。
  4. 重复 222 直到 aaa 数组清空。

注意:xxx 不能在运算过程中随意更改。

现在请你输出通过怎样的过程使 aaa 数组清空。

Solution

看数据范围做题,尽管 T≤1000T\le 1000T≤1000,但是题目保证了∑texecasen≤1000\sum_{texe\ case} n\le1000∑texe case​n≤1000 ,所以 TTT 可以忽略不计,随便暴力 n2n^2n2 可过。

老规矩先来分析一下有什么性质,我们的 xxx 最开始是两个数的和,消掉这两个数以后,我们的 xxx 就变成了这两个数中的最大值,而这个最大值,又对应着两个数的和,然后 xxx 又变成这两个数中最大值,但是却比最开始的 xxx 小,也就是说 xxx 一定会越来越小,所以当前序列中最大的数,一定要在 xxx 小于它之前被丢掉,也就是优先选择最大的数,以及另一个数的和为 xxx ,不然等 xxx 小于 它以后,这个最大的值就永远不可能被丢掉,也就不能实现丢掉全部元素的愿望。

所以我们的 xxx 最开始的时候一定是序列里最大的数,以及另一个数的和,至于另一个数应该是谁,才能使得中间过程刚好全部都能被凑齐,使得一步一步能够实现呢?我也不知道,这个没办法推出来,但是数据很小,我们可以暴力枚举,也就是先选择序列里最大的数,然后枚举另一个数,总和为 xxx 往下一层走,我们看是否存在当前序列(删掉之前选择的数后的序列)的最大的数和一个数的和等于 xxx ,在这个过程中保留选择的方案,一旦能够全部丢掉就输出方案即可。

然后就是我写的看起来非常蠢的大模拟代码了

注意我们的 visvisvis 数组,范围应该是 aaa 元素大小,初始化的时候要用 forforfor 循环把每一个 a[i]a[i]a[i] 清空然后再加起来,这样总体的时间复杂度是 O(n2)O(n^2)O(n2) ,vis数组大小是 10610^6106 ,在里面 O(n)O(n)O(n) 初始化的话时间复杂度就不对了。

Code

// Problem: C. Array Destruction
// Contest: Codeforces - Codeforces Round #696 (Div. 2)
// URL: https://codeforces.com/contest/1474/problem/C
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef int itn;
const int N = 5e3 + 7, M = 1e6 + 7, mod = 1e9 + 7;
const ll INF = 1e18 + 7;int n, m, t, k, q;
int a[N];
int vis[M];
PII ans[N];bool check(int aa, int bb, int pos)
{int cnt = 0;itn top = 2 * n;int x = aa + bb;while(true) {if(vis[x - a[top]] == 0) {return false;}vis[a[top]] -- , vis[x - a[top]] -- ;ans[ ++ cnt].x = a[top], ans[cnt].y = x - a[top];x = a[top];while(vis[a[top]] == 0) {top -- ;if(top == 0)return true;}}
}void solve()
{memset(vis, 0, sizeof vis);scanf("%d", &n);for(int i = 1; i <= 2 * n; ++ i) {scanf("%d", &a[i]);}sort(a + 1, a + 1 + 2 * n);int maxx = a[2 * n];for(int i = 1; i < 2 * n; ++ i) {for(int j = 1; j <= 2 * n; ++ j) vis[a[j]] = 0;for(int j = 1; j <= 2 * n; ++ j) vis[a[j]] ++ ;if(check(a[i], maxx, i)) {puts("YES");printf("%d\n", maxx + a[i]);for(int j = 1; j <= n; ++ j) {printf("%d %d\n", ans[j].x, ans[j].y);}return ;}}puts("NO");return ;
}int main()
{scanf("%d", &t);while(t -- ) {solve();}return 0;
}

D. Cleaning

Problem

你有一个长度为 nnn 的数组 aaa。

现在要进行一些操作将数组的所有元素清除:

选定两个下标连续的数,若两个数均不为 000,则将两个数均减 111。
在此之前,你可以使用一次超能力(可以不使用):任选两个下标连续的数并交换。

编写程序,判断是否可以清空 aaa 数组。

Solution

显然根据套路,我们只需要找到哪些是必须交换的,然后看它能不能交换即可。

因为显然交换的位置是在中间,所以我们可以两头扫一遍,先从左往右模拟一遍,一直修改到不能修改为止,标记不合法需要通过交换救命的位置,然后从右往左模拟一遍,找到不合法的位置,由于交换操作只能用一次,所以假设我们只能交换 iii ,则我们可以交换 iii 和 i+1i+1i+1 ,那么就变成了 a[i+1]a[i+1]a[i+1] 与 pre[i−1]pre[i-1]pre[i−1] 一起修改, a[i]a[i]a[i] 和 suf[i+2]suf[i+2]suf[i+2] 一起修改,如果二者修改后权值相同,则整体可以全部清空,否则就无解。

Code

// Problem: D. Cleaning
// Contest: Codeforces - Codeforces Round #696 (Div. 2)
// URL: https://codeforces.com/contest/1474/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 500007;int n, m, t;
int a[N], pre[N], suf[N];void solve()
{scanf("%lld", &n);pre[0] = 0, suf[n + 1] = 0;for(int i = 1; i <= n; ++ i) {scanf("%lld", &a[i]);pre[i] = suf[i] = 0;}for(int i = 1; i <= n; ++ i) {if(pre[i - 1] != -1) {if(a[i] >= pre[i - 1]) pre[i] = a[i] - pre[i - 1];else pre[i] = -1;}else pre[i] = -1;}for(int i = n; i >= 1; -- i) {if(suf[i + 1] != -1) {if(a[i] >= suf[i + 1]) suf[i] = a[i] - suf[i + 1];else suf[i] = -1;}else suf[i] = -1;}if(pre[n] == 0) {//不需要交换puts("YES");return ;}for(int i = 1; i < n; ++ i) {if(pre[i - 1] != -1 && suf[i + 2] != -1 && pre[i - 1] <= a[i + 1] && suf[i + 2] <= a[i]) {if(a[i + 1] - pre[i - 1] == a[i] - suf[i + 2]) {puts("YES");return ;}}} puts("NO");return ;
}signed main()
{scanf("%lld", &t);while(t -- ) {solve();}return 0;
}

E. What Is It?

Problem
Solution

显然只能进行 n−1n-1n−1 次操作,我们可以发现代价为 (n−1)2(n-1)^2(n−1)2 的操作只能进行一次,代价小于等于 (n−2)2(n-2)^2(n−2)2 的操作可以进行两次。即最后的最大代价为

(n−1)2+(n−2)2×2+(n−3)2×3+⋯+(n−⌈n2⌉)2×⌈n2⌉(n-1)^2+(n-2)^2\times 2+(n-3)^2\times 3+\dots+(n-\lceil \frac n 2\rceil)^2\times \lceil \frac n 2\rceil(n−1)2+(n−2)2×2+(n−3)2×3+⋯+(n−⌈2n​⌉)2×⌈2n​⌉

Code

F. 1 2 3 4 …


Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解(每日训练 Day.16 )相关推荐

  1. 【Codeforces Round #767 (Div. 2)】 C. Meximum Array 题解

    [Codeforces Round #767 (Div. 2) ]C. Meximum Array 题解 1629C: Meximum Array 题解 [Codeforces Round #767 ...

  2. Codeforces Round #696 (Div. 2)

    A. Puzzle From the Future (构造+贪心) 题目链接:传送门 &nsbp; 题意:给你一个二进制的数b,问你怎么凑出一个a使得c=a+b的二进制数最大,注意此处的加和并 ...

  3. Codeforces Round #744 (Div. 3)【A-D E的题解】

    目录 A. Elections[800 / 模拟] B. Make it Divisible by 25[900 / 思维] C. Save More Mice[1000 / 贪心] D1. All ...

  4. Codeforces Round #411 (Div. 1)(A~D)题解

    题目链接: #411 (Div. 1) 差点翻船. 题解: A.A. 这个推导一下,找一下规律就可以了.答案是:ans=(n+1)2−1ans=\frac{(n+1)}{2}-1. B.B. 容易发现 ...

  5. Codeforces Round #645 (Div. 2) D - The Best Vacation 题解(二分+思维)

    题目链接 题目大意 一年有n个月,每个月有d[i]天,让你找出连续x天,使其日期的总和最大,可以跨年 题目思路 这里要发现一个性质:即连续的x天一定满足最后一天在月份的结尾,结论是显然的. 然后用两个 ...

  6. Codeforces Round #641 (Div. 2) D. Orac and Medians 题解(思维)

    题目链接 题目大意 就是数组里一段数可以都变成他的中位数,问整个序列能不能变成k.可以变化很多次 题目思路 emmm,根本没什么思路,看了题解感觉根本想不到啊,但是仔细想想其实确实应该那么想. 先令a ...

  7. Codeforces Round #249 Div.2 435 BD两题题解

    B D B 给个长度最多为18的数字,交换相邻数字不超过k次,求能够产生的最大数字. 该贪心的要贪心. 很明显把大的数字换到最高位显然更好. 我们从最高位开始枚举iii,从i" role=& ...

  8. Codeforces Round #509 (Div. 2) A,B,C,D 题解

    这是蒟蒻的真·第一场CF...所以其实升了1500+还是不错吧? A. Heist 题意:找包含给出的n个数的最短连续序列,输出新加入的数的最小个数. 分析:排序+扫描即可. #include< ...

  9. Codeforces Round #645 (Div. 2) E - Are You Fired? 题解(思维)

    题目链接 题目大意 给你一个长为n的数组前(n+1)/2个数为a[i],后面的数为x,让你求出一个长度k使其所有连续为k的数组之和都大于0 题目思路 首先要找性质,如果k满足,那么显然k*2也满足那么 ...

最新文章

  1. 除了eWTP试验区,阿里云还要在马来西亚部署全球第15座数据中心
  2. python 参数类型的多态_【Python】面向对象:类与对象\封装\继承\多态
  3. Efficient Graph-Based Image Segmentation
  4. opencv学习笔记21:直方图和掩膜 原理及其应用
  5. android 屏幕保持唤醒 不锁屏 android.permission.WAKE_LOCK
  6. 如何把两个查询语句合成一条 语句
  7. UPS分类:直流UPS和交流UPS
  8. 论文浅尝 | CoRR - 面向复杂知识问答的框架语义解析方法
  9. 【LeetCode】剑指 Offer 33. 二叉搜索树的后序遍历序列
  10. java监听表变化_「Java Web开发」Filte(过滤器)、Listener(监听器)
  11. HDU2097 Sky数【进制】
  12. python基础补漏-03-函数
  13. 让ProgressPar动起来
  14. js中去除字符串中所有的html标签
  15. 【Hoxton.SR1版本】Spring Cloud Config服务配置中心
  16. stm32无源蜂鸣器定时器_【STM32H7教程】第20章 STM32H7的GPIO应用之无源蜂鸣器...
  17. FIR滤波器窗函数设计法——汉明窗设计实例
  18. 从2D图像生成3D模型,基于Im2Avatar
  19. 中兴新支点操作系统_中兴新支点系统预装测试
  20. 用计算机软件绘制思维导图,一款简单好用的在线免费思维导图制作工具

热门文章

  1. vue全家桶+Koa2开发笔记(2)--koa2
  2. Angular:Promise.all()的具体应用
  3. 爱送礼成中国好前任,谢谢你让我认识了快递员
  4. shell任务不受意外中断影响的常见方法
  5. 阿里云云服务器Centos7部署JDK8+Nginx+Tomcat8+Mysql5.7
  6. 用C语言实现素数筛法获取一亿(100000000)以内的全部素数
  7. linux 文件查找及定位
  8. java- ASM 字节码操控框架
  9. SQLite管理工具绿色
  10. 《.NET应用架构设计:原则、模式与实践》新书博客--试读-1.3 架构设计中的重要概念...