248小X的区间或值和
题解
题目描述
题目要求计算数组中所有可能的连续子数组的权值和,权值定义为子数组中所有选取两个元素按位或(OR)的值之和。最终结果需要对 (10^9 + 7) 取模。
思路分析
首先我们不妨考虑一个暴力一些的做法,计算所有数对的按位或值之和。
对于数对a[i]
和 a[j]
,$(0 <= i < j < n)$。想要连续子数组包含 a[i]
和 a[j]
,那么连续子数组的左端点$l$的范围为$0 <= l <= i$,连续子数组的右端点$r$的范围为$j <= r < n$。因此数对的贡献和为(a[i] | a[j]) * (i + 1) * (n - j)
所以我们只需要枚举所有数对,将贡献累加即可
这种方法的时间复杂度为 $O(n ^ 2)$,对于数组长度大于1e5
的情况会超时。
参考代码
1 |
|
这种方法的时间复杂度为 $O(n ^ 2)$,对于数组长度大于1e5
的情况会超时。
优化
- 因为每一个比特位之间相互独立,我们可以分开考虑每一位的贡献。
对于数对a[i]
和a[j]
的第k
个比特位,我们同样可以采用上述的暴力思路去枚举每个比特位之间的贡献。 - 当前比特位的大小是
1 << k
,同时注意到当我们固定a[i]
而去枚举a[j]
时,连续子数组左端点$l$的范围始终是$0<=l<=i$。那我们直接累加所有右端点的取值不就可以了!!! - 在实现时,我们枚举连续子数组的右端点而累加左端点的值, 根据按位与的性质,当前比特位为
1
时,左端点可以取任意的值,而当前比特位为0
时,只能和左端点包含1
的连续子数组产生贡献。
1 |
|
复杂度分析
- 时间复杂度:$O(nlogm)$,其中 (n) 是数组长度,(m) 是数组中最大值。
- 空间复杂度:$O(1)$,使用常数级额外空间。
248小X的区间或值和
https://kongshuilinhua.github.io/2024/12/29/248小X的区间或值和/