📌  相关文章
📜  给定数组中具有 GCD K 的三元组计数(1)

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

给定数组中具有 GCD K 的三元组计数

问题描述

给定一个长度为n的正整数数组arr和一个正整数k,找到满足以下条件的三元组(i, j, k)的数量:

  1. i < j < k
  2. arr[i], arr[j]和 arr[k]的GCD(最大公约数)等于k
解题思路

首先,我们可以统计出数组中每个数的出现次数,然后遍历每个可能的三元组(i, j, k),检查它们的GCD是否等于k。但是,这种方法的总时间复杂度为O(n^3)并不可取。

另一个更高效的解决方法是,对于给定的k,我们首先计算所有a_i mod k的值,得出长度为k的计数数组C。那么对于一个三元组(i, j, k),如果他们的GCD等于k,那么它们必须都具有C[k] 的倍数作为它们的模数。

因此,我们可以遍历C中所有的倍数p(p为k的倍数),统计所有满足条件的三元组数量。我们可以通过以下方式计算该三元组数量:

C(k) * C(p) * C(q)

其中,k, p,q是三个模数,且它们的最大公约数等于k。由于i < j < k,我们可以对k, p, q进行全排列,这样我们算的三元组数量就不会重复。

代码实现
def count_triplets(arr, k):
    n = len(arr)
    count = [0] * k
    for a in arr:
        count[a % k] += 1

    res = 0
    for i in range(1, (k+1)//2):
        res += count[i] * count[k-i] * 2

    if k % 2 == 0:
        res += (count[k//2] * (count[k//2]-1) // 2) * 2
    else:
        res += count[k//2] * (count[k//2]-1) * (count[k//2]-2) // 6
    res += count[0] * (count[0]-1) * (count[0]-2) // 6
    return res

其中,count数组表示每个模数的数量。然后,我们遍历所有的k的倍数p,统计三元组数量。

总结

本文介绍了如何在一个数组中统计所有满足GCD条件的三元组数量。我们首先使用计数数组优化了问题,并通过对模数的分析进一步优化了时间复杂度。时间复杂度为O(k^2+n)。