📌  相关文章
📜  计算无序对(i,j),以使a [i]和a [j]的乘积为2的幂(1)

📅  最后修改于: 2023-12-03 14:57:31.412000             🧑  作者: Mango

计算无序对(i,j),以使a[i]和a[j]的乘积为2的幂

本题要求计算给定序列中无序对(i,j),使得a[i]和a[j]的乘积为2的幂。具体来说,就是找到所有满足$2^k$ = $a[i] \times a[j]$的无序对(i, j)。

在处理本题时,可借助两个重要的数学性质:

  1. 若a[i]和a[j]都是2的幂,则它们的乘积也是2的幂。

  2. 在任意正整数n中,2的幂只有$log_2n$个。这一性质可用布尔运算来实现:若n为2的幂,则n & (n-1) == 0(&为按位与符号,==为相等判断符号)。

基于上述性质,暴力枚举i,j并检查它们的乘积是否为2的幂是可行的,但时间复杂度为O(n^2)。

因此,我们需要更高效的算法。具体来说,我们可以用一个字典(dict)或哈希表(hash)来记录序列a中已经出现过的数出现次数,这一步骤可以在时间复杂度O(n)内完成。

随后,我们可以枚举2的幂k,并找到满足条件的(i, j)。具体来说,对于当前的k,我们遍历字典中的所有元素a[i],若k-a[i]也在字典中出现,则表明存在一个数a[j],使得2^k = a[i] * a[j]。具体来说,此时的j即为k-a[i]。

最后,我们统计满足条件的无序对个数即可。

以下为Python实现代码片段:

def count_pair_for_power_of_2(a: List[int]) -> int:
    # 统计每个元素出现次数
    freq = {}
    for x in a:
        if x not in freq:
            freq[x] = 1
        else:
            freq[x] += 1
    # 枚举2的幂并计算无序对个数
    ans = 0
    for k in range(32):
        for x in freq:
            y = (1 << k) - x
            if y in freq and (y != x or freq[x] > 1):
                ans += freq[x] * freq[y]
        if k == 0:
            ans -= freq.get(0, 0)
    # 返回答案
    return ans // 2

备注:实现中的//操作符表示整数除法,即向下取整除法。其中 freq.get(0, 0)表示字典freq中获取元素0的值,若无此元素则返回0。