一句话总结:两个只能动一个
经过艰苦卓绝的努力,我们发现在 $a \geq b$ 时,答案为 $a - b$。原因很简单:这时除了将 $b$ 加一,我们的任何操作都会让 $a$ 变大,而无益于让二者相等。
这就让我们可以用 $b$ 控制 $a$ 的大小,让数据范围中的值域限制有了意义。
注意到执行一次操作 3 就会让 $a$ 变得不小于 $b$。这样就会落入 $a \geq b$ 的情况中,最优策略是固定的了。
所以我们最多执行一次操作 3。
那么,我们需要决策的,就仅仅是在这次操作之前,操作 1 和操作 2 的执行情况。
一种方法是枚举让 $a$ 加了多少,让 $b$ 加了多少。但平方复杂度肯定会超时。
回收伏笔:两个只能动一个。也就是说,操作 1 和操作 2 中至少有一种没有被执行。
证明:假设操作 1 执行了 $i$ 次,操作二执行了 $j$ 次。
那么我们的总代价就是 $i + j + ((a + i) \text{ or } (b + j)) - (b + j)$。
整理,得到 $i + ((a + i) \text{ or } (b + j)) - b$,注意到 $-b$ 是常数,所以我们的目标就是最小化 $i + ((a + i) \text{ or } (b + j))$。
这个式子里 $j$ 只出现了一次。那么我们考虑,固定 $i$,哪个 $j$ 是最优的?
肯定是使 $((a + i) \text{ or } (b + j))$ 最小的 $j$ 最优。这是废话。
设 $b' = b + j, a' = a + i$。
但注意此时有 $b + j > a + i$。所以 $b'$ 二进制下的位数不少于 $a'$。或上 $a'$ 不会影响高位,但会影响低位(即 $a'$ 的最高位以下的部分)。
我们要让 $b'$ 加上一个值,之后低位上的或的结果就会变小。注意到我们不能影响高位,否则一定不优。那么只需要考虑优化低位,低位里我们跟 $a'$ 对齐(保持一样)即可。
可能 $a'$ 甚至不如 $b'$ 的低位大,但这不影响,我们反过来让 $a'$ 和 $b'$ 的低位变成一样即可,这个过程一定是不劣的,因为对于 $b'$ 低位中的 $1$,加上这一位的代价和好处是抵消的,而可能还有一些低位的 $0$,就提供更多的好处。
这时我们让 $a'$ 和 $b'$ 同时变小 1,发现答案变优了($a'$ 或 $b'$ 变小之后低位部分整体就变小了)。于是我们不停做这个操作,直到做不动为止。什么时候会做不动呢?就是 $i$ 或 $j$ 为 $0$ 的时候。
于是我们就证明了这个关键结论。剩下的就是写两遍循环,分别枚举 $i$ 和 $j$。
代码:
| |