CodeForces 高分段 dp 选做

发布时间 2023-07-01 13:34:02作者: Rain__Song

选取方式:CF *3000+ 按通过人数排序。

CF1188D Make Equal

\(cnt(x)\) 表示 \(x\) 二进制下 \(1\) 的个数,题目等价于求 \(x\) 使得

\[\sum_{x=1}^n cnt(x + a_n - a_i) \]

最小。

\(a_i = a_n - a_i\)

从低位到高位考虑,假设当前要决策第 \(k\) 位,我们需要知道:

\(1.\) \(x\) 在这一位的值

\(2.\) \(a_i\) 在这一位的值

\(3.\) 之前的决策引起的进位

其中第三部分比较棘手,但是如果不考虑更高的位,那么 \(\mod 2^{k}\) 越大的 \(a\) 显然越容易进位,于是我们在每一位的决策是把所有 \(a\)\(\mod 2^{k}\) 从大到小排序,那么进位的一定是一个前缀,直接枚举这个前缀,设 \(f_{i,j}\) 表示考虑前 \(i\) 位,第 \(i\) 位有 \(j\)个进位的最小答案,简单讨论转移,时间复杂度 \(O(n \log n \log a)\)

总结:

  • 可以先设计一个暴力 dp 状态,然后利用性质转移(实际上笔者在做题是先想到了按 \(\mod 2^k\) 分类,但是误以为是贪心,导致没有做出本题)
  • 利用偏序关系化简状态,某些指数级的状态按顺序做就可能降为多项式级别