问题描述
小K有一个数组,她定义数组的权值为数组中任选两个数的按位与的值之和。具体来说,对于数组中的每个连续子数组,我们可以计算所有可能的两个元素的按位与值之和,并将这些值相加。小K想知道该数组中所有可能的连续子数组的权值和是多少,最后结果对10^9 + 7取模。
问题分析
我们需要计算数组中所有可能的连续子数组的权值和。数组的权值定义为数组中任选两个数的按位与的值之和。由于直接计算所有可能的连续子数组的权值和可能会导致时间复杂度过高,我们需要寻找更高效的算法。
思路
- 按位与的性质:按位与操作的结果取决于两个数的二进制表示。如果两个数的某一位都是1,则结果的这一位也是1,否则是0。
- 子数组的权值:对于数组中的任意两个数 a[i]a[i] 和 a[j]a[j](i≤ji≤j),它们在子数组 a[i:j+1]a[i:j+1] 中的按位与值 a[i]&a[j]a[i]&a[j] 只依赖于 a[i]a[i] 和 a[j]a[j] 的二进制表示。
- 重复计算:对于数组中的每个数 a[i]a[i],它在多个子数组中出现,且在这些子数组中的按位与操作中会被重复计算。我们可以利用这一点来优化算法。
代码
MOD = 10**9 + 7
def solution(n: int, a: list) -> int:
total_sum = 0
for i in range(n):
for j in range(i, n):
for k in range(i, j + 1):
for l in range(k + 1, j + 1):
total_sum += a[k] & a[l]
total_sum %= MOD
return total_sum
test_cases = [
(4, [2, 3, 1, 2], 16),
(3, [5, 6, 7], 25),
(2, [1, 10], 0),
(5, [1, 2, 4, 8, 16], 0)
]
results = [solution(n, a) == expected for n, a, expected in test_cases]
results
步骤
- 初始化:定义一个变量
total_sum用于存储最终的权值和。 - 遍历数组:使用两个嵌套循环,分别以 ii 和 jj 作为子数组的起始和结束索引。
- 计算权值:对于每个子数组 a[i:j+1]a[i:j+1],计算所有可能的两个元素的按位与值之和,并累加到
total_sum。 - 取模:由于结果可能非常大,每次累加后都对 109+7109+7 取模。
时间和空间复杂度
- 时间复杂度:最坏情况下,我们需要计算 O(n2)O(n2) 个子数组的权值,每个子数组的权值计算需要 O(n)O(n) 的时间,因此总的时间复杂度是 O(n3)O(n3)。
- 空间复杂度:我们只使用了常数个额外空间,所以空间复杂度是 O(1)O(1)。