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

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

题目介绍

给定一个长度为 $n$ 的整数数组 $a$ 和一个给定的正整数 $K$,计算有多少个三元组 $(i,j,k)$ 满足 $1 \le i < j < k \le n$ 且 $gcd(a_i,a_j,a_k)=K$。

解题思路

首先,我们可以发现 $gcd$ 具有传递性,即 $gcd(a_i,a_j,a_k)=K$ 等价于 $gcd(\frac{a_i}{K},\frac{a_j}{K},\frac{a_k}{K})=1$。

因此,我们可以先将数组 $a$ 中所有的数都除以 $K$,转化为求三元组 $(i,j,k)$ 满足 $1 \le i < j < k \le n$ 且 $gcd(a_i,a_j,a_k)=1$。

接着,我们可以枚举所有的 $i$,然后枚举 $j$,注意 $j$ 要从 $i$ 的后一个位置开始枚举。然后我们可以使用一个 unordered_map 记录当前位置 $j$ 之前(不包括位置 $j$)每一个位置 $t$ 出现的所有因子,并统计因子个数。最后用整个数组中出现过的所有因子的个数减去不合法的因子个数即为答案。

时间复杂度

本题的时间复杂度为 $O(n\sqrt{a_{max}}\log a_{max})$。

参考代码

int countTriplets(vector<int>& arr, int K) {
    int n = arr.size();
    for (int i = 0; i < n; i++) {
        arr[i] /= K;
    }

    int ans = 0;
    unordered_map<int, int> mp;
    for (int i = 0; i < n; i++) {
        int factors = 0;
        for (int j = arr[i]; j > 1; j /= mp[j]) {
            factors++;
        }

        ans += i * (i - 1) / 2 - (n - i) * (n - i - 1) / 2;
        ans -= mp[1] + mp[arr[i]];
        mp[arr[i]] += factors;
    }

    return ans;
}