查找XOR总和等于零的数组数

时间:2020-04-13 12:52:01

标签: algorithm

如何确定长度为N的数组的数量,使其满足以下两个条件:

  1. 每个数组的值都在0-5之间(含0和5)。
  2. 该数组所有值的XOR总和为0。

示例:让 N = 2

然后将XOR总和为零= 6的总数组

是- (0,0) (1,1) (2,2) (3、3) (4、4) (5,5)

那么如何有效地找出这一点呢?

1 个答案:

答案 0 :(得分:4)

可以使用dynamic programming O(N)中完成。

假设dp[i][j]是许多数组,这样它们就有i个元素,它们的XOR和为j

请注意0 <= j <= 7,因为如果N == 6数组[1, 2, 4, 4, 2, 1]匹配,但是其前缀[1, 2, 4]具有XOR-sum7。同样,您将无法获得更多XOR-sum。比7大,因为分解为2的幂时,0到5范围内的所有数字除2 ^ 2、2 ^ 1和2 ^ 0之外都不能有其他项。

以下是使用先前计算的值来计算dp[i][j]的公式:

dp[i][j] = 0
# k is XOR-sum of previously calculated number of arrays of length i-1.
for k in range(0, 8):
    # x is a number we append to arrays of length i-1 so XOR-sum is j.
    x = j xor k
    if x <= 5:
        dp[i][j] += d[i - 1][k]

这就是其余的代码:

# Assume there's a two dimensional array of integers dp of size N+1 x 8.

# Dynamics initialization.
# There's only one possible array of length 0: []. It's XOR-sum is 0.
dp[0][0] = 1 
for i in range(1, 8):
    dp[0][i] = 0

# Dynamics state calculation.
for i in range(1, N+1):
    for j in range(0, 8):
        # Here comes code from above.
        dp[i][j] = 0
        for k in range(0, 8):
            x = j xor k
            if x <= 5:
                dp[i][j] += d[i - 1][k]

# Answer is dp[N][0].
print(dp[N][0])

动态状态计算进行 N * 8 * 8 次迭代,因此复杂度为 O(N)(请注意,尽管存在线性复杂度,常数64可能会很大)。

有一种方法可以使用matrix binary exponentiation O(log N)中对其进行计算。简要地说:您需要计算一个8x8的矩阵M 告诉dp[i-1][*]值如何变成dp[i][*]值;然后计算dp[0] * M^N,其中dp[0][1, 0, 0, 0, 0, 0, 0, 0](与动态初始化完全一样)。