Count Array Pairs Divisible by K

hard hashing gcd number theory

Problem

Given a 0-indexed integer array nums of length n and an integer k, return the number of pairs of indices (i, j) with 0 ≤ i < j ≤ n − 1 such that the product nums[i] * nums[j] is divisible by k.

Inputnums = [1,2,3,4,5], k = 2
Output7
The pairs (0,1), (0,3), (1,2), (1,3), (1,4), (2,3), (3,4) have products 2, 4, 6, 8, 10, 12, 20 — all divisible by 2.
Inputnums = [1,2,3,4], k = 5
Output0
No product of two elements is a multiple of 5.

def count_pairs(nums, k):
    from math import gcd
    count = {}
    ans = 0
    for x in nums:
        g = gcd(x, k)
        for g2, c in count.items():
            if (g * g2) % k == 0:
                ans += c
        count[g] = count.get(g, 0) + 1
    return ans
function countPairs(nums, k) {
  const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
  const count = new Map();
  let ans = 0;
  for (const x of nums) {
    const g = gcd(x, k);
    for (const [g2, c] of count) {
      if ((g * g2) % k === 0) ans += c;
    }
    count.set(g, (count.get(g) || 0) + 1);
  }
  return ans;
}
long countPairs(int[] nums, int k) {
    Map<Integer, Integer> count = new HashMap<>();
    long ans = 0;
    for (int x : nums) {
        int g = gcd(x, k);
        for (var e : count.entrySet()) {
            if ((long) g * e.getKey() % k == 0) ans += e.getValue();
        }
        count.merge(g, 1, Integer::sum);
    }
    return ans;
}

int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
long long countPairs(vector<int>& nums, int k) {
    unordered_map<int, int> count;
    long long ans = 0;
    for (int x : nums) {
        int g = __gcd(x, k);
        for (auto& [g2, c] : count) {
            if ((long long) g * g2 % k == 0) ans += c;
        }
        count[g]++;
    }
    return ans;
}
Time: O(n · d(k)) Space: O(d(k))