CF2013 D,E 题解
唉,CF的场次号马上要到2024了。
只做了 D E,两道题想明白的话,代码都相当之短。
D:
题意: 给你一个数列,你可以操作无数次,将左边数-1,右边数+1,请最小化极差。
Solution:
这题看完题发现和牛客多校那道签到题好像,不是好像,是一模一样。
所以知道做法了,不过那题是暴力风吹沙,这题 n 范围 1e5 还要用单调栈模拟,用单调栈模拟每个高度的数有几个,比较难写(相比于正解),还有些小细节:
正解代码相当之短,我们根本不用模拟风吹沙的过程。
我们最大值和最小值单独算。假设向右吹沙不是以整数为单位的,而是可以有小数。枚举可能成为最低的位置 i ,如果有多个最低位置取最右,那么这个最低的位置就是前 i 个数字的平均数(要么前 i 个位置可以平齐,要么前面有更低的位置),将所有位置取最小值。
最大值和最小值是正好相反的,你可以把数组高度全部取负数,那么风吹沙的方向从向右变成了向左。具体的,若位置 i 是最高位置,那么这个高度就是 i 后缀这些数字的平均值(或者后面有更高的位置)。
要注意我们要把小数转化为整数,求最小值时,直接除以 i 自然下取整即可,求最大值时,只要有余数答案就加一,可以让总数先加 n-i+1。
具体看代码:
E:
题意:给你数组a,你可以随意排序,最小化 。
Solution:
本以为是一道神仙题,结果竟然是个结论题。
结论就是,让 a1 等于最小值,然后每次找一个与前面 gcd 最小的数放在后面,当 gcd 取到最小的时候后面所有位置 gcd 都不变了。
由于在 gcd 取到最小值之前每次向后添加一个数字会让最小值至少除以2,因此只需要找 log 次,每次暴力枚举复杂度也没问题。
怎么证明这就是最优解呢?要靠一个不等式:当 时, 。
如上图,如果 A 与前面圆圈的 gcd 是 a,B 与圆圈的 gcd 是 b,若 a<b ,我们把 A 移动到 BCDE 的前面,证明下面这些位置的和小于上面。
首先红色部分下面要靠后,因此下面不超过上面;蓝色部分上方有一个 b,和最后位置,下面有一个 a,和 ,即使上面最后一个位置是1,b 一个数字就足以让上面大于等于下面。
所以把A放前面会使整体答案变小,如果能找到更小的,继续再放 A 前面即可。贪心的策略就是这么证明的。
CF1614D:
这是一个和 E 题很像的题,唯一的区别就是求最小值变成了求最大值,这题就不能再用贪心结论了。
这题可以设计一个调和复杂度的 dp,还挺妙的。
设 表示数组里有几个 i 的倍数, 表示 gcd 为 i 的子序列答案最大值。 ,其中 j 是 i 的倍数。初值 。
easy version不需要线性筛,只要枚举倍数就能做,hard version再加些小技巧。
D1代码:
__EOF__

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具