阿里笔试T1:异或和与GCD

考查注意力的纯数学“算法题”

有一个长度为$n$的数组$a$,数组中每个元素都是整数,取值范围是$[0, 10^{9}]$。设$b$是$a$的一个子数组。

定义$b$的异或和为$b$中所有元素的异或运算结果,即$f(b) = b[0] \oplus b[1] \oplus \cdots \oplus b[k]$。

定义$b$的GCD为$b$中所有元素的最大公约数,即$g(b) = GCD(b[0], b[1], \cdots, b[k])$。

你可以从$a$中选择任意一个子数组$b$,满足$f(b) \cdot g(b)$尽可能大吗?请你算一算这个最大值。

这题其实用了一个结论:

$$ \boxed{\max { f(b) \cdot g(b) } = (\max a_i)^2} $$

也就是说,所求的最大值 就是数组最大元素的平方,与数组的元素分布无关。我们来证明一下:

证明

对于任意子数组 $b$,设其最大元素为 $M$,则有重要结论: $$ f(b) \triangleq b_0 \oplus b_1 \oplus \cdots \oplus b_k < 2M $$

一个数组的异或和严格小于最大元素的2倍

这部分的证明:

  • 设 $M$ 的二进制最高位为第 $k$ 位(即 $M \in [2^k, 2^{k+1})$)。
  • 异或操作的每一位结果独立,最高位为1的次数若为奇数次,则结果最高位为1;否则为0。
  • 无论奇偶,异或和的最高位不可能超过 $k+1$ 位,即严格小于 $2^{k+1} \leq 2M$。

我们再分析 $g(b)$ 的上界。子数组的 GCD 满足:

  • 如果$b$的元素都相同,则$g(b) = M$。
  • 如果$b$的元素不全相同,则 $\displaystyle g(b) \leqslant \frac{M}{2}$。

这个也很好证明。如果全相同,显然成立。如果不全相同,由于一个数的最大因数(除这个数本身)不大于这个数的一半,所以数组的最大公约数不大于最大元素的一半。

那么,现在有两种情形:

  • 如果子数组的元素都相同,则:
    • 当$n$为偶数时,$f(b) = 0$,$g(b) = M$,$f(b) \cdot g(b) = 0$。
    • 当$n$为奇数时,$f(b) = M$,$g(b) = M$,$f(b) \cdot g(b) = M^2$。
  • 如果子数组的元素不全相同,则:
    • $f(b) < 2M$,$\displaystyle g(b) \leqslant \frac{M}{2}$,$f(b) \cdot g(b) < M^2$。

这就证明了: $$ \max { f(b) \cdot g(b) } = M^2 $$ 只需取子数组为单元素 $M$,即可达到理论最大值。

用到的结论

  • 一个正整数数组的异或和严格小于最大元素的2倍。
  • 一个正整数数组的最大公约数不大于最大元素的一半。

代码

1public class Solution {
2    public static int maxXorGcd(int[] a) {
3        int max = 0;
4        for (int i = 0; i < a.length; i++) {
5            max = Math.max(max, a[i]);
6        }
7        return max * max;
8    }
9}