📜  所有子阵列的XOR之和(1)

📅  最后修改于: 2023-12-03 15:25:44.421000             🧑  作者: Mango

所有子阵列的 XOR 之和

当我们给定一个长度为 $n$ 的数组时,其子阵列即为该数组中所有可能的连续子序列。对于每个子阵列,我们可以将其元素进行异或操作,得到一个异或和。问题则是,如何计算该数组的所有子阵列的异或和的总和?

思路

设 $dp[i]$ 表示数组前 $i$ 个元素的所有子阵列的异或和的总和,则 $dp[i]$ 的值由两部分组成:

  1. 所有包含第 $i$ 个元素的子阵列的异或和
  2. 所有不包含第 $i$ 个元素的子阵列的异或和

对于第一部分,我们可以考虑以第 $i$ 个元素作为子序列的末尾时,其前面可以有 $i-1$ 个位置作为该子序列的开头,因此以第 $i$ 个元素作为末尾的子序列数为 $i$ 个。由此可得:

$$ \text{第一部分的值} = \sum_{j=0}^{i-1} (a_j \oplus a_i) $$

其中 $\oplus$ 表示异或操作。不难发现,该式实际上是一个前缀异或和数组 $pre$ 的推导式,即:

$$ \text{第一部分的值} = (i-1) \times (a_i \oplus pre_{i-1}) $$

对于第二部分,则可以通过数学归纳法证明其值与前 $i-1$ 个元素构成的子序列的异或和总和相等,即:

$$ \text{第二部分的值} = dp[i-1] $$

最终,我们可以得到:

$$ dp[i] = dp[i-1] + (i-1) \times (a_i \oplus pre_{i-1}) $$

代码实现
def xor_subarray_sum(arr: List[int]) -> int:
    n = len(arr)
    pre_xor = [0] * n
    for i, num in enumerate(arr):
        pre_xor[i] = num if i == 0 else pre_xor[i-1] ^ num
    dp = [0] * n
    dp[0] = arr[0]
    for i in range(1, n):
        dp[i] = dp[i-1] + (i * (arr[i] ^ pre_xor[i-1]))
    return dp[-1]
参考资料