@Dmaxiya
2026-09-01T13:01:33.000000Z
字数 2424
阅读 14
Codeforces
给定 根胡萝卜,长度分别为 ()。
有一台切割机,每次操作可以同时选择任意多根胡萝卜(已切出的也可以再选),并对每根被选的胡萝卜执行:若其长度 则不变,否则切成 和 两段( 为正整数,每次操作可不同)。
对于每个 ,问恰好使用 次操作后,最多能选出多少根长度完全相同的胡萝卜(所有选出的长度必须一致)。
每个 独立求解,互不影响。
若我们希望最终得到尽量多长度为 的胡萝卜,那么对于每一根原始胡萝卜,最优的切割顺序是从大到小切:
即第一刀先切出 的块(如果原长度足够),第二刀切 ,依此类推。这样能保证在 刀内获得尽可能多的 小块。
设当前操作次数为 ,目标长度为 。令:
对于某一根长度为 的胡萝卜:
解释:
- 是长度 理论上最多能包含的 的个数。
- 但由于只有 次切割,最多只能切出 个完整的 小块(因为要得到 个整块需要恰好的整除条件,否则缺一刀)。
- 两者取小即为实际贡献。
当 固定时,若目标长度 太大,使得 ,则没有任何胡萝卜能触发“特殊贡献”,且所有 都会很小甚至为 0,答案必然劣于取更小的 。
因此最优解只需要考虑:
若 ,则唯一有用的 是 ,且此时答案就是所有胡萝卜长度之和(因为全部切成 1)。
如果直接枚举每个 和每个 ,再对 根胡萝卜求和,复杂度为 ,不可接受。
我们需要利用长度值域 和前缀和来加速。
cnt[1..m],其中 cnt[v] 表示长度为 的胡萝卜的数量。则任意区间 内的胡萝卜总数可在 得到:
对于固定的 ,将所有胡萝卜按 的值分组。
令 ,则 相同的胡萝卜长度落在区间:
这些胡萝卜的数量可以直接用前缀和求出:
这一组对总答案的贡献为:
我们将 从 到 全部累加,就得到了常规部分的总贡献。
当存在长度为 的胡萝卜时,这些胡萝卜在常规部分被算作 ,贡献为 ,少算了 。
因此需要额外加上:
(仅当 时存在)
对于固定的 ,内层循环次数为 。
有效的 范围是 ,且 。
对所有 求和:
当 时,,实际运行效率完全可行,题解中记为 (将对数平方视作小常数)。
预处理 和 需要 ,总复杂度满足题目限制。
切割顺序最优性:
每次切出当前最大可获得的 块,保证在 次内最大化 小块数量,这是贪心最优(可通过归纳证明)。
贡献公式的正确性:
对任意长度 ,它至多包含 个 ,且 次切割最多产生 个完整小块(除非正好整除产生 个)。公式精确刻画了这两种情况。
枚举范围的正确性:
若 ,则 ,没有任何胡萝卜能贡献 ,且所有 或很小,答案不会超过取 的情况,因此可忽略。
分段求和正确性:
将所有胡萝卜按 分组,同组贡献相同,利用前缀和统计数量,结果等价于逐项累加。
