📜  计算Array中乘积为任何正整数的Kth幂的对(1)

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

计算Array中乘积为任何正整数的Kth幂的对

本文介绍了如何在给定一个数组后,计算其中乘积可以表示成任何正整数 K 的幂的两个数之间的对数。

算法思路

我们可以首先计算数组中所有数的 GCD。这个 GCD 就是我们可以快速检查一个数是否为幂数的最大幂数,因为任何不为 GCD 的正整数都不能进行 K 的整数倍幂分解。

接着,我们可以将数组中的每个数除以 GCD,得到一个新的数组。这个新数组中的每个数可以表示成 $a_i = g_i k_i^k$ 的形式,其中 $g_i$ 是 GCD,$k_i$ 是任意正整数。

我们考虑固定数组中的一个数 $a_i$,我们需要找到另外一个数 $a_j$,满足 $a_j = g_j k_j^k$,使得 $a_i a_j = g_i g_j k^k$ 是 K 的幂。 根据乘法原理,我们只需要分别计算 $k^k$ 是 $g_i g_j$ 的因子的正整数对数和不是 $g_i g_j$ 的因子的正整数对数,两个数相加即可。

对于前一种情况,我们可以预处理 $g_i g_j$ 的因子集合,通过判断 $k^k$ 是否在这个集合中来计数。

对于后一种情况,我们可以使用 Inclusion-Exclusion Principle(容斥原理),对每个 $g$ 计算不是 $g$ 的因子的正整数对数,然后依次进行容斥操作。

代码实现
def count_pairs(arr, k):
    # 计算所有数的 GCD
    gcd = arr[0]
    for i in range(1, len(arr)):
        gcd = math.gcd(gcd, arr[i])

    # 将数组中的每个数除以 GCD
    new_arr = [a // gcd for a in arr]

    # 预处理每个数的因子集合
    factor_sets = []
    max_val = max(new_arr)
    for i in range(max_val + 1):
        factors = set()
        for j in range(1, int(math.sqrt(i)) + 1):
            if i % j == 0:
                factors.add(j)
                factors.add(i // j)
        factor_sets.append(factors)

    # 计算符合条件的正整数对数
    res = 0
    for i in range(len(new_arr)):
        factors = factor_sets[new_arr[i]]
        if k in factors:
            res += len(factors) - 1  # 计算不是自己的因子的正整数对数
        for j in range(i + 1, len(new_arr)):
            if new_arr[i] * new_arr[j] % k == 0:
                gcd_ij = math.gcd(new_arr[i], new_arr[j])
                factors = factor_sets[gcd_ij]
                if k in factors:
                    res += 2  # 计算符合条件的正整数对数

    return res
性能分析
  • 时间复杂度:$O(n \log n + N \sqrt{N} + n^2)$,其中 $n$ 是数组的长度,$N$ 是所有数除以 GCD 后的最大值。
    • 计算所有数的 GCD 时间复杂度为 $O(n \log n)$。
    • 计算所有数的 GCD 后,将数组中的每个数除以 GCD 的时间复杂度为 $O(n)$。
    • 预处理每个数的因子集合的时间复杂度为 $O(N \sqrt{N})$,因为每个数都有 $\sqrt N$ 个因子。
    • 计算符合条件的正整数对数的时间复杂度为 $O(n^2)$。
  • 空间复杂度:$O(N \sqrt{N} + n)$,因为需要存储每个数除以 GCD 后的结果以及每个数的因子集合。