21. Count the Coprimes
β GFG solution to the Count the Coprimes problem: count pairs with GCD=1 using MΓΆbius function and inclusion-exclusion principle for efficient computation. π
The problem can be found at the following link: π Question Link
π§© Problem Description
You are given an array arr[]
of positive integers. Your task is to count the number of pairs (i, j)
such that:
0 β€ i < j β€ n-1
gcd(arr[i], arr[j]) = 1
In other words, count the number of unordered pairs of indices (i, j)
where the elements at those positions are co-prime (their greatest common divisor is 1).
π Examples
Example 1
Input: arr[] = [1, 2, 3]
Output: 3
Explanation: (0,1), (0,2), (1,2) are the pair of indices where gcd(arr[i], arr[j]) = 1
Example 2
Input: arr[] = [4, 8, 3, 9]
Output: 4
Explanation: (0,2), (0,3), (1,2), (1,3) are the pair of indices where gcd(arr[i], arr[j]) = 1
π Constraints
$2 \le \text{arr.size()} \le 10^4$
$1 \le \text{arr}[i] \le 10^4$
β
My Approach
The optimal approach uses the MΓΆbius Function with Inclusion-Exclusion Principle to efficiently count coprime pairs without checking every pair individually:
MΓΆbius Function + Inclusion-Exclusion
Core Insight:
Instead of checking all pairs individually (O(nΒ²) with GCD computation), we use number theory.
Count pairs with specific GCD values using inclusion-exclusion principle.
MΓΆbius function helps eliminate overcounting in inclusion-exclusion.
Algorithm Steps:
Step 1: Find maximum element and create frequency array
cnt[]
.Step 2: Compute MΓΆbius function
mu[]
using sieve method.Step 3: For each divisor
d
, count how many elements are divisible byd
(store indiv[]
).Step 4: Apply inclusion-exclusion: pairs with GCD=1 = total pairs - pairs with GCD>1.
Step 5: Use MΓΆbius function to compute the final result efficiently.
MΓΆbius Function Properties:
ΞΌ(1) = 1
ΞΌ(n) = 0
if n has squared prime factorΞΌ(n) = (-1)^k
if n is product of k distinct primesUsed to invert inclusion-exclusion formulas
Mathematical Formula:
For each divisor
d
: ifmu[d] β 0
anddiv[d] > 1
Add
mu[d] * div[d] * (div[d] - 1) / 2
to resultThis counts pairs where GCD is exactly 1 using inclusion-exclusion
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(n log n), where n is the maximum element in array. The first term is for sieve-based MΓΆbius computation, and the second term is for divisor counting across all elements.
Expected Auxiliary Space Complexity: O(n), where n is the maximum element. We need arrays for frequency counting, divisor sums, MΓΆbius function values, and visited markers during sieve computation.
π§βπ» Code (C++)
class Solution {
public:
int cntCoprime(vector<int>& arr) {
int mx = *max_element(arr.begin(), arr.end());
vector<int> cnt(mx + 1), div(mx + 1), mu(mx + 1, 1);
vector<bool> vis(mx + 1);
for (int x : arr) cnt[x]++;
for (int i = 1; i <= mx; ++i)
for (int j = i; j <= mx; j += i)
div[i] += cnt[j];
for (int i = 2; i <= mx; ++i) {
if (!vis[i]) {
for (int j = i; j <= mx; j += i) {
mu[j] *= -1;
vis[j] = 1;
}
for (long long j = (long long)i * i; j <= mx; j += (long long)i * i)
mu[j] = 0;
}
}
int ans = 0;
for (int i = 1; i <= mx; ++i)
if (mu[i] && div[i] > 1)
ans += mu[i] * div[i] * (div[i] - 1) / 2;
return ans;
}
};
π§βπ» Code (Java)
class Solution {
int cntCoprime(int[] arr) {
int mx = Arrays.stream(arr).max().orElse(0);
int[] cnt = new int[mx + 1], div = new int[mx + 1], mu = new int[mx + 1];
boolean[] vis = new boolean[mx + 1];
for (int x : arr) cnt[x]++;
Arrays.fill(mu, 1);
for (int i = 2; i <= mx; ++i) {
if (!vis[i]) {
for (int j = i; j <= mx; j += i) {
mu[j] *= -1;
vis[j] = true;
}
for (long j = (long)i * i; j <= mx; j += (long)i * i)
mu[(int)j] = 0;
}
}
for (int i = 1; i <= mx; ++i)
for (int j = i; j <= mx; j += i)
div[i] += cnt[j];
int ans = 0;
for (int i = 1; i <= mx; ++i)
if (mu[i] != 0 && div[i] > 1)
ans += mu[i] * div[i] * (div[i] - 1) / 2;
return ans;
}
}
π Code (Python)
class Solution:
def cntCoprime(self, arr):
mx = max(arr)
cnt, div, mu = [0] * (mx + 1), [0] * (mx + 1), [1] * (mx + 1)
vis = [False] * (mx + 1)
for x in arr:
cnt[x] += 1
for i in range(2, mx + 1):
if not vis[i]:
for j in range(i, mx + 1, i):
mu[j] *= -1
vis[j] = True
for j in range(i * i, mx + 1, i * i):
mu[j] = 0
for i in range(1, mx + 1):
for j in range(i, mx + 1, i):
div[i] += cnt[j]
ans = 0
for i in range(1, mx + 1):
if mu[i] and div[i] > 1:
ans += mu[i] * div[i] * (div[i] - 1) // 2
return ans
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated