1 条题解
-
0
C. XOR-distance 题解
题意回顾
给定三个整数 ,要求在 的范围内选取 ,使得 达到最小,并输出该最小值。
问题转化
令 。由于异或运算是按位独立的,我们可以逐位分析 的取值对结果的影响。
不妨设 (若 则交换两者,不影响答案)。对于某一位 :
- 若 和 在第 位上相同(同为 或同为 ),则无论 该位取何值,异或后 和 的该位依然相同,差值在该位上不受影响。
- 若 和 在第 位上不同,则必定一个是 一个是 。由于 ,在最高的不同位上,一定是 的该位为 , 的该位为 。在该位异或 的对应位会同时翻转两个数的该位:原本为 的变成 ,为 的变成 。因此,若 的该位为 ,则 和 在该位上的大小关系会反转( 的位变成 , 变成 ),这会使 减少 ;若 的该位为 ,则保持原状,差值不变。
我们的目标是最小化 (因为 且异或后两者大小关系可能变化,但绝对值保证了非负)。因此,我们希望在某些不同位上通过令 来缩小差距,同时要满足 的限制。
贪心策略
从最高位向最低位考虑(例如从第 位到第 位):
-
第一个不同的位
这是 与 的最高不同位。在这一位上, 为 , 为 。如果我们令 的这一位为 ,会使得原本较大的 变小、较小的 变大,可能导致 ,从而差值变为 ,但这并不一定比保持原样更优。事实上,保持第一个不同位的原状可以保留 的“优势”,使得后续有更多的机会通过翻转其他位来减小差距。因此,对于最高不同位,我们选择不翻转( 该位取 )。 -
后续的不同位
对于之后遇到的每一位 ,如果 和 在该位不同,则由于高位已经确定大小关系,此时 的该位仍为 , 为 。如果我们令 的这一位为 ,则 增加 , 减少 ,总差值减少 。
显然,只要加上这一位的 后 仍然不超过 ,我们就应该执行这一翻转,因为它严格减小最终差值且不会破坏高位已经建立的大小关系(因为高位不同位的取值已经固定,低位翻转不会改变 的大局)。如果翻转会导致 ,则不能进行,只能取 。
这种贪心选择能够保证在限制 下差值尽可能小。正确性基于:每一位的贡献是独立的,且高位翻转的影响远大于所有低位翻转的总和(因为 )。因此,在第一个不同位之后,只要有机会减小差值且不超限,就立即执行是最优的。
算法步骤
- 读入 。
- 若 ,交换 ,使 。
- 初始化 ,标志变量
first_bit = true表示尚未遇到第一个不同位。 - 从高位到低位遍历(例如 到 ):
- 获取 和 在第 位的值。
- 若两值不同:
- 若是第一个不同位,则将
first_bit置为false,不做其他操作。 - 若不是第一个不同位,且 的该位为 (即 的该位为 ),并且 ,则:
- 同时将 和 的该位翻转(
a ^= (1<<i),b ^= (1<<i)),以模拟 的影响,便于后续计算差值。
- 若是第一个不同位,则将
- 输出 。
时间复杂度:每个测试用例 ,总复杂度 ,轻松通过。
参考代码
#include <bits/stdc++.h> using namespace std; const int maxb = 60; bool get_bit(int64_t a, int i) { return a & (1ll << i); } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { int64_t a, b, r; cin >> a >> b >> r; int64_t x = 0; bool first_bit = true; if (a > b) swap(a, b); for (int i = maxb - 1; i >= 0; --i) { bool bit_a = get_bit(a, i); bool bit_b = get_bit(b, i); if (bit_a != bit_b) { if (first_bit) { first_bit = false; } else { if (!bit_a && x + (1ll << i) <= r) { x += (1ll << i); a ^= (1ll << i); b ^= (1ll << i); } } } } cout << b - a << "\n"; } return 0; }
细节说明
- 由于 ,故最高位只需考虑到第 位即可。
- 代码中
x的累加用于判断是否超过 ,但并不需要真正输出 ,因此可以省略对 的实际异或操作,直接维护当前差值并计算潜在收益,但直接修改 亦无妨,逻辑更直观。 - 若 在初始时高位就有多个不同位,第一个不同位不处理,后续按贪心尽可能翻转,最终差值即为答案。
- 1
信息
- ID
- 6513
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者