C. Trip to the Olympiad 解题思路
核心目标与异或性质分析
本题要求在给定范围 $[L, R]$ 内,找到三个互不相同的数字 $a, b, c$,使得目标和 $\text{Sum} = (a \oplus b) + (b \oplus c) + (c \oplus a)$ 最大。
我们首先分析异或和的性质。对于任意一个二进制位 $i$,它对总和 $\text{Sum}$ 的贡献是 $ 2^i$ 乘以该位上三个异或结果 $(a \oplus b)_i, (b \oplus c)_i, (c \oplus a)_i$ 之和。
在一个特定的位 $i$ 上,数字 $a, b, c$ 的位值(bit values)只有四种组合会产生非零贡献:
- $(0, 0, 1)$ 或其排列: 此时 $(a \oplus b)_i = 0, (b \oplus c)_i = 1, (c \oplus a)_i = 1$。总和为 $ 0 + 1 + 1 = 2$。
- $(1, 1, 0)$ 或其排列: 此时 $(a \oplus b)_i = 0, (b \oplus c)_i = 1, (c \oplus a)_i = 1$。总和为 $ 0 + 1 + 1 = 2$。
- $(0, 0, 0)$ 或 $(1, 1, 1)$: 此时所有异或结果均为 $ 0$。总和为 $ 0$。
因此,要使总和 $\text{Sum}$ 最大,我们应该尽量使高位的三个数字在该位上呈现 $(0, 0, 1)$ 或 $(1, 1, 0)$ 的模式,以保证每一位都能贡献最大值 $ 2 \cdot 2^i$。
寻找关键位 $k$
由于 $a, b, c$ 必须在 $[L, R]$ 范围内,我们不能随意构造数字。最大的挑战在于范围约束。
我们考虑范围的两个端点 $L$ 和 $R$。它们之间的最高不同位是限制我们能构造出多少高位 $ 1$ 的关键。
- 计算 $L \oplus R$: 得到一个数,其最高位 $k$ 标志着 $L$ 和 $R$ 在 $ 2^k$ 这一位上是不同的,而在所有更高的位( $k+1, k+2, \dots$ )上是相同的。
- 确定关键位 $k$: $k$ 即为 $L \oplus R$ 的最高设置位(Most Significant Bit, MSB)的索引。
- 如果 $L = R$,则 $L \oplus R = 0$,此时 $k=0$(或 $-1$,我们取 $k=0$ 作为安全底线)。
- 如果 $L \neq R$,则 如果 $L \neq R$,则 $k$ 为 $L \oplus R$ 的最高设置位(MSB)索引,且 $k > 0$。
构造最优解 $a, b, c$
在位 $k$ 以上,所有 $[L, R]$ 范围内的数字都与 $L$ 和 $R$ 相同。我们最大化目标和的潜力在于位 $ 0$ 到 位 $k$。为了最大化贡献,我们希望 $a, b, c$ 在这 $k+1$ 位上实现全 $ 1$ 模式的最高贡献。
我们构造两个数 $a$ 和 $b$ 如下:
构造 $a$: 我们取 $L$ 的高位部分,并在位 $ 0$ 到 位 $k-1$ 上全部设置为 $ 1$。
这样构造的 $a$ 满足 $L \le a \le R$ 的条件,因为它只在 $L$ 的低位上做了“或 $ 1$”操作,且 $L$ 和 $R$ 在位 $k$ 上不同。
构造 $b$: 我们希望 $b$ 能实现与 $a$ 在位 $k$ 上的翻转,并使低位部分尽可能贡献 $ 1$。
分析 $a$ 和 $b$:
- $a$ 在位 $k$ 以下全为 $ 1$。
- $b = a+1$ 将使位 $k$ 以下全变为 $ 0$,并使位 $k$ 上的值从 $a$ 的值翻转(即 $a_k \neq b_k$)。
- 由于 $a$ 是由 $L$ 通过“或 $ 1$”操作得到的,它必然满足 $L \le a \le R$。
- $b = a+1$ 必然满足 $L \le b \le R$。这是因为 $R$ 的高位部分与 $L$ 相同,但 $R$ 的位 $k$ 是 $ 1$,而 $L$ 的位 $k$ 是 $ 0$。$a$ 和 $b$ 相当于取到了这个范围内的“最大跨度”数字。
构造 $c$: 既然 $a$ 和 $b$ 已经实现了在关键位 $k$ 上的翻转,以及在所有低位上对 $\text{Sum}$ 的最大贡献(通过 $a$ 在 $k-1$ 位以下全是 $ 1$),剩下的第三个数字 $c$ 只需要满足:
- $L \le c \le R$
- $c \neq a$ 且 $c \neq b$(题目要求互不相同,但实际上对于最大化 $\text{Sum}$ 的影响不大,只要有三个数能达到最大 $\text{Sum}$ 即可)。
最简单的取法是取 $c = L$ 或 $c = R$,只要它不与 $a$ 或 $b$ 重复即可。由于范围 $[L, R]$ 至少包含 $ 3$ 个数,我们可以保证找到一个不重复的 $c$。
例如,我们简单取 $c = (a == L ? R : L)$。
C++ 代码实现
1 |
|

