加载中...

CF 1015 div1+2(A~E)

虽然这一场没有打好,但感觉这一场需要反思的地方很多,遂记录。

A

赛时直接看样例猜规律了。

\(n\) 为奇数时,显然 \(n, 1, 2, ..., n - 1\) 合法。
\(n\) 为偶数时,可以证明 \(n\) 放在哪里都不合法(证明略)。

code

B

显然等式左侧的最小值一定是整个数组的最小值,否则最小值在等式右侧的 \(gcd\) 部分,由于 \(gcd\) 的递减性,其值一定 \(<=\) 整个数组的最小值。而等式左侧的 $min > $ 整个数组的最小值,显然矛盾。

因此问题等价于从 去除了其中某一个最小值后 的数组中选出一些数,使得它们的 \(gcd\) 等于整个数组的最小值。显然这些数一定是该最小值的倍数。再利用 \(gcd\) 的递减性,直接取所有最小值的倍数并计算 \(gcd\),看是否等于最小值即可。

完整思路想到了,但还是吃了一发 wa2——是由于自己没想清楚瞎特判导致的。因此以后对于某道题,能想出正解一定要往正解上想,尽量少依赖特判。

code

C

赛时出的速度倒也不慢,但感觉还是写得太麻烦了,而且这种维护映射的题目也做过不少,却并没对快速解出这道题有太多帮助。思路很简单,难点在于实现,因此就不多说思路了。

维护的操作本质上相当于:给定一些字符,它们能两两组成回文串,但被打乱了。每次可以交换两个字符的位置,需要你将这个串经过任意次交换操作重新变成回文串,并要记录交换操作。

赛时的想法是,直接用 \(set\) 实时维护每个字符的两个位置(\(n\) 为奇数时特判),暴力模拟。但代码看上去比较臃肿。

但思来想去,觉得虽然自己写得比较麻烦,但思路是非常清晰易懂的。看了哥哥与tourist等大佬简洁的代码也看得不是很懂(蒟蒻对于这种嵌套映射维护还是有些畏惧的。。。)。那就先把代码放在这里吧,等蒟蒻以后能变强一些再慢慢领悟。

code1

补:看了 yvbf 叔叔发的视频讲解,感觉很不错,遂补上。

code2

D

一道并不难的构造题,但牢了 2h 也没写出来,而实际代码量不超过5行。本题也是蒟蒻最想反思的一道题。

先反思自己为什么没想出来:还是犯了自己之前犯过多回的大忌:往一个自己认为很对,但实际上不对的思路猛想,并觉得自己想得很对而不去变通。其实当遇到这样的情况时,让脑子重新变得清醒起来,再去看这道题,并重新加以理解,是完全可以在短时间内做出来的。

现在再重新深入思考一下这道题的来龙去脉:

其实这道题说是构造题,但本质上是一个博弈题:你 与 对这个序列做删除操作的人 博弈,你构造一个尽可能让最终 \(mex\) 最大的序列,他尽可能让你构造的序列在经过操作后 \(mex\) 最小。

而对于 \(mex\),应当想到贪心。那么考虑对手做删除操作时会怎样做:他一定会先想办法将你的序列内的所有 \(0\) 删除;如果发现做不到,再去考虑能不能将所有 \(1\) 删除,以此类推。

那么你需要做的事情就很明显了:假设你的预期答案为 \(mex\),那么你需要保证:对于数字 \(0到mex-1\),无论他怎样操作,都不能被删除。而想让这个 \(mex\) 尽可能大,就需要在有限的 \(n\) 个数中,尽量用最少的数字来保证“ \(0到mex-1\) 不会被删除” 这一点,并将剩下的数字用于继续扩大 \(mex\)

那么就来考虑:怎样保证 \(0到mex-1\) 不会被删除呢?

先说结论:对于任意一种相同的数字(比如 \(0\)),它们的两两间隔至少为 \(k\)。这样可以保证每次删除时,这个数字最多只会被删除一次。感性理解一下这一点会是比较优的构造方式。

再考虑最多删除 \(m\) 次这个操作:显然他删除的数越多对他越有利。因此可以等价于恰好删除 \(m\) 次。那么对于每种数,要想保证在所有操作后不被删除,一个必要条件是:该数在序列中出现次数至少为 \(m + 1\) 次。

综合考虑这两点,可以发现:连续 \(m + 1\)\(0 到 k - 1\) 的循环序列看上去是非常好的构造方法,事实上也是如此。这样可以保证 \(0 到 k - 1\) 中的每个数字都不会被删除。

但其实 \((m + 1) \times k\)\(n\) 的大小关系是不确定的。因此需要分类讨论一下:

  1. \((m + 1) \times k <= n\):前面所说的 连续 \(m + 1\)\(0 到 k - 1\) 的循环序列一定能被构造出来,因此 \(mex\) 至少为 \(k\)。还可以添加一些数,考虑让 \(mex\) 变得更大:无非就是加入一些 \(k, k + 1\) 之类的数。那么对手在操作时,会发现 \(0 到 k - 1\) 一定不会被删除,于是会想尽办法删除你的 \(k, k + 1\) 这些 \(>= k\) 的数。若想保证它们不会被删除,则最好的办法就是:在前面构造的连续 \(m + 1\)\(0 到 k - 1\) 的循环序列中顺次添加更大的数字。这样的话间隔会逐渐变大,但还能保持 “每次删除时,这个数字最多只会被删除一次” 这一性质。再考虑 “每个数最多出现 \(m + 1\) 次即可”,正确性更加显然。
    那么这种情况的构造方式就出来了:最大可构造的数即为 \(n / (m + 1)\),这样可保证序列中含有至少 \(m + 1\) 个完整的循环节 \(0, 1, ... , n / (m + 1)\)\(mex\) 至少为 \(n / (m + 1)\)

  2. \((m + 1) \times k > n\):也就是前面所说的 连续 \(m + 1\)\(0 到 k - 1\) 的循环序列不能被完整构造出来。但显然仍需要保证 “它们的两两间隔至少为 \(k\)。这样可以保证每次删除时,这个数字最多只会被删除一次” 这一性质。而由 \(k \times m < n\) 这个性质可知,只有最后一个循环节不能被完整构造出来。那么这种情况的构造方式便是:循环节长度仍然为 \(k\),舍去完整循环序列中最后一个循环节的后半段即可。此时最大 \(mex\)\(n - m \times k\)

code

E

待补。。。

code

posted @ 2025-04-06 19:50  jxs123  阅读(27)  评论(0)    收藏  举报