传送门
A. Little Artem
签到。
Code
/*
* Author: heyuhhh
* Created Time: 2020/4/8 22:36:43
*/
#include
#include
#include
#include
#include
#include
#include
#include
B. Kind Anton
签到。
Code
/*
* Author: heyuhhh
* Created Time: 2020/4/8 22:50:49
*/
#include
#include
#include
#include
#include
#include
#include
#include
C. Eugene and an array
题意:
给定一个序列,询问该序列含有多少个连续子区间,满足该子区间中不含有任意一段其和为\(0\)。
思路:
得到序列\(a\)的前缀和数组\(sum\),那么区间\([l,r]\)和为\(0\)等价于\(sum_{l-1}=sum_r\)。
那么从后往前枚举区间左端点,维护最远的区间右端点计算答案即可。
Code
/*
* Author: heyuhhh
* Created Time: 2020/4/8 22:58:55
*/
#include
#include
#include
#include
#include
#include
#include
#include
D. Challenges in school №41
题意:
\(n\)个人占成一列,每个人都有一个朝向,若两个人面面相对则可以在一次操作中他们两个人朝向进行翻转。
一次操作中可以选择多对满足条件的人进行翻转。
问是否能在恰好\(k\)次操作使得不存在两个人面面相对。
思路:
- 抽象成给出一个\(01\)串,若遇到\(10\)则交换这两个数。
- 容易发现操作过程类似于冒泡排序,因此总的交换次数不会超过\(n^2\)。
- 因此暴力交换即可,用一个\(vector\)存储操作最少的情况下每次操作最多交换的对数。
- 之后贪心来凑\(k\)即可。
细节见代码:
Code
/*
* Author: heyuhhh
* Created Time: 2020/4/9 0:12:01
*/
#include
#include
#include
#include
#include
#include
#include
#include
E. Road to 1600
题意:
\(n*n\)棋盘上有两种棋子,每种棋子行动路径分别如下:
现在每个格子上有一个\(1\)~\(n*n\)大小的权值,两个棋子分别从\(1\)出发,按照以下规则进行行走:
- 到达当前行动路径上权值最小且没有被访问过的格子,将其标记访问;
- 若当前行动路径上格子都被访问,那么花费\(1\)的代价到达一个权值最小且未被访问过的格子;
- 若所有格子已被访问,那么停止操作。
现在要求构造一种权值方案,使得第一种棋子消耗的代价小于第二种棋子所消耗的代价。
思路:
这个题乍一看神仙构造题,对于\(n\)较大的情况,两种棋子的行走规律完全无法琢磨。但是注意到两种棋子存在重合的路径,也就是说两个棋子在横竖方向可以按照相同的路径行走。
\(n\)较小的情况我们可以手动进行构造,易发现\(n=1,2\)时不存在合法方案,\(n=3\)的情况可能会存在合法方案。这时我们可以暴力打表/手动构造出合法的方案。
\(n>3\)呢?此时依旧可以暴力打表,但这个题直接暴力计算时间复杂度不能承受。
注意到刚才提到的性质:两个棋子在水平或者垂直方向可以走相同的路径。
那么对于\(n>3\)的情况,我们只需要两个棋子都从外圈往里绕,那么问题即可转化为\(n=3\)的情况了。
总结一下:1.构造出小数据的合法解;2.利用性质将规模缩小,转化为较易求解的问题。
Code
/*
* Author: heyuhhh
* Created Time: 2020/4/9 16:41:05
*/
#include
#include
#include
#include
#include
#include
#include
#include
F. Kate and imperfection
题意:
给定一个\(1...n\)的集合。
现在回答对于所有\(size=k,k\geq 2\)的集合,\(max\{gcd(a_i,a_j),i\not ={j},a_i,a_j\in subset_k\}\)为多少。
思路:
有两种思路来思考这个题,一个是正向考虑,另一个是反向考虑。
先考虑正向求解:
- 从小到达枚举答案,考虑贪心加入一些数使得答案不超过枚举值。
- 当\(ans=1\)时,显然我们需要加入\(1\)和所有的质数;
- 当\(ans=x\)时,我们只需要考虑加入\(x\cdot p_j,p_j\leq p_i\),其中\(p_i\)为\(x\)的最小质因子。
简要证明如下:
不妨设我们加入的\(p_j>p_i\),那么加入的数\(s=x\cdot p_j\),考虑我们枚举答案到\(\frac{x}{p_i}\)时:
- 假设我们此时加入\(s\)能使得答案更优,那么之前我们加入\(t=\frac{x}{p_i}\cdot p_j\)也能使得答案更优,然而\(gcd(s,t)>x\),所以假设不成立。
以上情况有特例,即当\(x=1\)时,\(x\)不存在最小质因子,此时我们贪心选取所有素数即可。
证毕。
那么以上做法就是对的了。其实根据以上做法我们可以进一步归纳,每个数被选入集合中的答案即为\(\frac{x}{p_i}\)。所以最后按照这个排个序输出即可。
代码如下:
Code
/*
* Author: heyuhhh
* Created Time: 2020/4/9 15:53:38
*/
#include
#include
#include
#include
#include
#include
#include
#include
反向考虑的话即是按照答案从大到小考虑:
- 若\(ans=n\),易求得此时最大\(gcd=x\);
- 之后会依次删除一个数,那么我们每次肯定会删除\(x\)的倍数,直至留下一个\(x\)的倍数,那么答案就会减小。
这种思考起来较为简单,但是代码写起来会麻烦一些。