📌  相关文章
📜  计算对(i,j)的对数,以使arr [i] * arr [j] = arr [i] + arr [j](1)

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

计算对(i,j)的对数,以使arr[i]*arr[j]=arr[i]+arr[j]

这个题目可以通过枚举所有的i和j,判断它们是否满足要求来解决。但是如果直接这样做的话,时间复杂度为O(n^2),这对于数据很大的情况来说是不可行的。

我们可以通过转换等式的形式来简化问题。假设arr[i]和arr[j]都不为0,那么可以将等式化简为:

1/arr[i] + 1/arr[j] = 1/(arr[i]*arr[j] - 1)

这个等式的左侧可以看作是一个斜率为正的直线,右侧可以看作是一个拱形曲线。因为右侧的曲线是单峰的,因此我们可以将它看作是一个凸函数。

我们可以通过计算每个元素在曲线上的投影来判断这个元素是否符合要求。具体来说,设arr[k]的投影为(p, q),那么arr[k]就符合要求,当且仅当:

  • p和q都是正整数;
  • arr[k] == arr[p]*arr[q] - 1。

可以用一个哈希表来记录每个元素在曲线上的投影情况。

时间复杂度:O(nlogn + n)

下面是这个算法的实现代码:

from collections import defaultdict

def count_pairs(arr):
    n = len(arr)
    proj = defaultdict(list)
    for i in range(n):
        if arr[i] == 0:
            continue
        for j in range(i):
            if arr[j] == 0:
                continue
            prod = arr[i] * arr[j]
            if prod - 1 in proj:
                for p, q in proj[prod-1]:
                    if i != p and j != p and i != q and j != q:
                        return True
            if prod <= n:
                proj[prod].append((i, j))
                proj[prod].append((j, i))
    return False

其中,proj记录了每个元素的投影情况。对于每个i和j,我们都判断一下它们的积是否在proj中出现过,如果出现过并且符合要求,那么就找到了一对符合要求的(i, j)。由于此题只需要输出对数,所以直接统计符合要求的对数即可。