📅  最后修改于: 2023-12-03 14:57:31.412000             🧑  作者: Mango
本题要求计算给定序列中无序对(i,j),使得a[i]和a[j]的乘积为2的幂。具体来说,就是找到所有满足$2^k$ = $a[i] \times a[j]$的无序对(i, j)。
在处理本题时,可借助两个重要的数学性质:
若a[i]和a[j]都是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。