Codeforces Round 929 (Div. 3)
[题目链接](https://codeforces.com/contest/1933)
A. Turtle Puzzle: Rearrange and Negate
题意
有一个长度为n的数组a,进行两步操作,第一步重新排列数组内元素的顺序, 第二部选择一个连续区间,将其中的元素取反。问进行完这两步操作后,**数组元素的值的总和** 最大是多少。
思路
很显然,把所有的负数放到一起,然后把这段区间取反即可。答案就是所有数的绝对值的和。
代码
1 |
|
B - Turtle Math: Fast Three Task
题意
给n个数, 每次你可以选择如下操作之一 ,
- 删除一个数
- 使一个数的值加一
问最少需要几步可以使得所有数的总和是3的倍数。
思路
我们考虑不进行操作时的总和,
- 总和本身就是3的倍数,不需要操作,直接输出0
- 总和除以3之后余2, 对任意数进行加一操作即可,输出1 。
- 总和除以3之后余1, 那么有两种选择,一是 删除一个**“除以3余1的数”** ,二是进行两次加一操作。因此可以记录一下是否存在**“除以3余1的数”** ,如果存在就输出1,不存在就输出2
代码
函数之外的代码与A题相同。
1 | void solve(){ |
C. Turtle Fingers: Count the Values of k
题意
给出 , 那么有 ,问有几种可能。
如 ,那么可以选择
共六种可能 。
思路
暴力枚举即可。需要检查当 (或者)不再是的因子时,及时break。 以及在枚举过程中可能出现重复的k,使用set去重即可。
代码
1 | void solve(){ |
D. Turtle Tenacity: Continual Mods
题意
给出数组 判断是否可能存在重排后的数组b, 使得。
思路
我们先找到最小的数
如果a数组中只有一个, 那么我们考虑把排在最前面,这样每次取模后得到的结果都是,最终的答案也就是,一定不为0。
考虑如果有多个mn,那么我们必须用另一个数 来取模 , 从而得到一个比mn更小的数, 借此t 变成了新的最小的数,并且一定唯一。
因此只要存在一个数,他不是mn的倍数,我们就可以让他作为num,这样就可以使得t不为0 ,最终使得答案是t。
总的来说,决策思路为:如果最小数的数量大于1,并且不存在使得不是的倍数,就无解,其他情况均有解。
代码
1 | void solve(){ |
E - Turtle vs. Rabbit Race: Optimal Trainings
题意
给出n个区间,他们从左到右并列相接。长度分别为 , 现在你会选择其中相邻的几个区间, 假设为第 个到 第 个区间, 那么你就相当于要学习undefinedsum _{i=l}^r a_iiu -i + 1$ , 如果你学的天数过多,可能在某一天增加的分数为负数。
接下来有多组询问, 每次给出 和 ,你需要找到一个r, 使得你得到的总分数最大。 如果存在多个r 使得分数最大, 那么输出最小的r。
思路
我们可以发现,当学习u天过后, 再学习会减少总分数。 我们维护一个前缀和数组sum, 那么我们只需要找到一个r,使得 与 的差的绝对值尽可能小 。 而由于a是正整数, 因此数组是单调递增的,我们在sum数组中使用二分查找位于 附近的两个位置,然后选出其中更靠近u的即可。
代码
注意使用寻找的r下标可能会超出n,应该取
找出的最终的r可能会比l要小(因为进行了r - 1操作) , 因此最终还要取
可以计算出两个r的
1 | void solve(){ |
F - Turtle Mission: Robot and the Earthquake
题意
在一个n*m的地图中, 你最初位于undefined0,0)(n-1,m-1)$ 。但是地图上会有一些石头, 他们每单位时间都会向上**循环移动**一格,(**循环移动**指的是当移动出地图边界时,会出现在地图的另一侧)
保证最右边一列不存在石头。
你每次可以选择向 **上,下,右**三个方向移动。其中上下方向为循环移动。
如果你向下移动,那么由于石头在向上移动, 如果你的下方两格中存在石头,你就会撞上石头。

同样,如果你向右移动,并且右下方有石头,也会撞上石头

问能否到达终点,如果能就输出最小步数,不能则输出-1
思路
机器人到达最后一列后,没有了石头,就很好办了。所以我们重点考虑机器人如何最快地到达最后一列。
由于每次石头都向上移动, 并且机器人和石头都是循环移动,因此我们可以认为石头不动,而机器人向下移动。这样机器人本身的向下移动就变成了向下移动两格,机器人的向右移动变成了向右下移动。
由此,我们就将本题的重点转化为了终点为最右一列的任意一点,起点为(0,0) 的广度优先搜索 。 于是我们使用队列来找到最少步数,以及此时的坐标(相对石头的坐标)。由于终点不会像石头那样不断向上移动, 因此每走一步,终点都相对于石头**向下移动了一格** 。
此时我们可以得到当前位置相对于石头的坐标为undefinedx,m-1)step((n-1+step)\ mod \ n,m-1)$ 。
设此时终点的横坐标为,即 。这时我们可以选择两种方法到达终点,直接到达,花费时间, 或者穿越边界再到达终点,花费 。二者取min即可。
代码
需要注意,不能像普通的走迷宫一样,直接将墙壁位置的设置为来省去mp数组:
考虑循在同一列循环的情况, 可能发生如下情况:现在位于undefined3,1)(3,3)(3,2)vis[3][2]vis[3][2]=1(3,2)vis[3][2]=1$ 出现了两种不同的结果,这是不被允许的。
1 | int mp[1005][1005]; |
