Codeforces Round 930 (Div. 2)
Codeforces Round 930 (Div. 2)
[题目链接](https://codeforces.com/contest/1937)
A. Shuffle Party
题意
给出一个数组 起初 ,之后定义 操作为 : 找到最大的,不等于的因子 ,交换和 。
下面令 ,依次进行 ,问最终数值会在哪个位置。
思路
数值1会随着不断运行swap来移动位置,我们可以观察1的移动轨迹。
于是我们模拟一下操作会发现, i = 2时, 此时1移动到了位置2 。接下来若想要让位置2发生交换,那么就必须找到一个最小的k,使得这个k所对应的d恰好是2 。 并且k尽可能地小。 于是我们想到了2的2倍4 。 下一步数值1便从位置2 移动到了位置4。接下来就是4的2倍即8, 数值1又从位置4移动到了位置8 。 这样循环往复,直到数值1移动到了 , 并且满足 。数值1便无法移动,此时就是他的最终位置。
代码
找到小于n的最大的2的次幂即可。
1 |
|
B. Binary Path
题意
有一个的 地图,一个蚂蚱从undefined1,1)(2,n)$ 。每次可以**向右或者向下走** ,蚂蚱走到终点后,会形成一个路径,问这个路径的字典序最小情况是什么, 以及有多少种走法可以出现这种最小字典序的路径。
思路
刚开始看错题了呜呜呜
为了使字典序最小,我们可以总结出如下几个策略:
如果右边的数和下边的数 , 一个是0,而另一个是1,那么走0那个方向一定字典序更小。
如果右边的数和下边的数相等, 那么走右边方向,因为一旦向下走到第二行走便不能回第一行,而在第一行则可以随时转去第二行。
如果很难理解策略2,可以尝试理解一下这个例子:
000111011111
当位于起点时,右边和下边都是0 ,但此时若向下走,则之后只能向右走而导致最终路径为0011111 ,若向右走则是0001111 。
于是我们便得出了最优解的路线,再考虑这种方案数:
我们可以发现只有当已经走到了第n列,或者下方为0并且右方为1时, 会选择向下走。那么我们假设在 时选择了向下走。
那么多种方案的出现仅有可能是由于可以提前选择向下走(在时选择了向下走),并且路径完全相同。
于是每当 便可以选择提前一格向下走,从而增多一种方案。于是总的方案数变为了: 对于 , 都有,而尽可能小来使得的可取数量尽可能多 。即在p之前的一些连续格子中,有多少个格子满足 **右边和下边的数相等** 。
代码
在实现代码时,有一些可能会有帮助的小技巧。
我们使用作为当前所在的行,flag = 0表示当前位于第一行,flag = 1表示当前位于第二行。循环枚举从到表示列,于是求路径时便可以用 来得到。
我们可以通过比较 和 的大小关系来进行操作 。
如果 则表示需要向下走,于是便可以设置flag = 1。 但我们发现当i = n时不论如何都要向下走,于是我们不妨提前将设置为2,表示无论 为何值,此时 都会成立,便选择了向下走。
而向下走时,i并不会变化,但for循环会使得i每次都加1,于是我们可以使用
i--来抵消每次for循环产生的i++我们用表示已经出现几个
右等于下的格子了,如果 ,那么就让cnt++如果 ,那么我们就需要重置cnt为0 。
下面是完整核心代码(只有solve()部分,其他部分和A题相同 ,所以如果不知道rep是什么可以看A题中的define声明)
1 | void solve(){ |
C. Bitwise Operation Wizard
题意
这是一个交互题,有一个长度为n的数组pundefinedp_1,p_2,…,p_n)(0,1,2,…,n-1)(a,b,c,d)p_a | p_bp_c | p_d<.=.>i,jp_i \oplus p_j\oplus$ 表示按位异或)
思路
我们考虑 最大为多少。 较容易得知 ,若n-1的二进制表示有k位。 那么最大值就是这k位全部为1。 即整个数组中的最大数**mx** ,与另一个数的异或。 接下来我们分别找这两个数。
为了找, 我们发现这个数就是在这位中,对的各位取反得到的数。 (如若 那么)
先找到最大值,我们发现可以令 这样裁判就会明确指出某两个数的大小关系。 于是我们可以这样子枚举整个数组,进行挨个儿比较。就可以用 次确定 **最大数** 所处的位置。
1 | for(int i = 1;i<=n-1;i++){ |
之后我们找所有的满足 为最大(即k位全是1) 的数的集合。 他们一定满足了对于上数位为的位置,的那个位置一定为 。
我们使用vec来记录数据,每当遇到更大的 就清空vec并放入 ,如果遇到了相等的数,就继续向vec中装入。
这样就可以在n次询问下得到所有的满足对于mx上数位为0的位置,num的那个位置一定为1 的数,那么我们为了发现,在中数位为1的位置上,num必须是0才能保证二者异或得到1。 也就是说要在vec中找到0最多的那个数,也就是最小的那个数。
于是我们可以在次询问下,得到vec中最小的数mn。
于是num就是mn,我们的最终答案就是 mn和mx。
代码
1 |
|
