📜  位大小最大为X并且按位或等于X的对的计数(1)

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

位大小最大为X并且按位或等于X的对的计数

这个问题需要我们找出一个数列中,有多少对数的按位或值相等且所在的位置的数值都小于等于 X。这个问题可以用位运算和计数排序来解决。

解法
思路

首先,我们需要计算出输入的数列中,对于任意一个位置 i,所能遇到的最小的符合条件的位置 j 是多少。

我们可以从 X 的最高位开始遍历每个位置,对于每一位,我们分别统计这个位置上值为 1 的数在整个数列中的出现次数。我们可以用计数排序来完成这个任务,得到一个长度为 n 的数组 counts。其中,counts[i] 表示小于等于 i 的数在输入列表中出现的次数。

我们可以倒序遍历数列,对于每个位置 i,我们可以用以下方式计算出符合条件的最小位置 j:

max_j = (X OR nums[i]) // X 的二进制表示下,i 位及以前都为 1
j = X & max_j   // 把 i 位及以前的位置都置为零

我们在 num_counts 数组中,找到小于等于 max_j 的位置上出现过的数的总数,再找到小于等于 j 的位置上出现过的数的总数,这两个总数相减即可得到符合条件的对数。

最后,我们把每个位置上符合条件的对数累加起来即可得到最终的结果。

代码
def count_pairs(nums, X):
    counts = [0] * (X+1)
    for num in nums:
        for i in range(X.bit_length()):
            if num >> i & 1:
                counts[i] += 1
    
    num_counts = [0] * (X+1)
    for num in nums:
        num_counts[num] += 1
    
    for i in range(1, X+1):
        num_counts[i] += num_counts[i-1]
    
    pairs = 0
    for num in reversed(nums):
        max_j = (X | num) >> 1
        j = X & max_j
        if j < X:
            pairs += num_counts[max_j] - num_counts[j]
    
    return pairs
结论

这道题的时间复杂度为 O(n log X),其中 n 是输入列表的长度。