Find the length of the Largest subset such that all elements are Pairwise Coprime
Given an array A of size N, our task is to find the length of the largest subset such that all elements in the subset are pairwise coprime that is for any two elements x and y where x and y are not the same, the gcd(x, y) is equal to 1.
Note: All array elements are <= 50.
Examples:
Input: A = [2, 5, 2, 5, 2]
Output: 2
Explanation:
The largest subset satisfying the condition is: {2, 5}
Input: A = [2, 3, 13, 5, 14, 6, 7, 11]
Output: 6
Naive Approach:
To solve the problem mentioned above we have to generate all subsets, and for each subset check whether the given condition holds or not. But this method takes O(N2 * 2N) time and can be optimized further.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int largestSubset( int a[], int n)
{
int answer = 0;
for ( int i = 1; i < (1 << n); i++) {
vector< int > subset;
for ( int j = 0; j < n; j++) {
if (i & (1 << j))
subset.push_back(a[j]);
}
bool flag = true ;
for ( int j = 0; j < subset.size(); j++) {
for ( int k = j + 1; k < subset.size(); k++) {
if (__gcd(subset[j], subset[k]) != 1)
flag = false ;
}
}
if (flag == true )
answer = max(answer, ( int )subset.size());
}
return answer;
}
int main()
{
int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 };
int N = sizeof (A) / sizeof (A[0]);
cout << largestSubset(A, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int gcd( int a, int b)
{
if (a == 0 )
return b;
if (b == 0 )
return a;
if (a == b)
return a;
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
static int largestSubset( int a[], int n)
{
int answer = 0 ;
for ( int i = 1 ; i < ( 1 << n); i++)
{
Vector<Integer> subset = new Vector<Integer>();
for ( int j = 0 ; j < n; j++)
{
if ((i & ( 1 << j)) != 0 )
subset.add(a[j]);
}
boolean flag = true ;
for ( int j = 0 ; j < subset.size(); j++)
{
for ( int k = j + 1 ; k < subset.size(); k++)
{
if (gcd(( int )subset.get(j),
( int ) subset.get(k)) != 1 )
flag = false ;
}
}
if (flag == true )
answer = Math.max(answer,
( int )subset.size());
}
return answer;
}
public static void main(String args[])
{
int A[] = { 2 , 3 , 13 , 5 , 14 , 6 , 7 , 11 };
int N = A.length;
System.out.println(largestSubset(A, N));
}
}
|
Python3
import math
def largestSubset(a, n):
answer = 0
for i in range ( 1 , ( 1 << n)):
subset = []
for j in range ( 0 , n):
if (i & ( 1 << j)):
subset.insert(j, a[j])
flag = True
for j in range ( 0 , len (subset)):
for k in range (j + 1 , len (subset)):
if (math.gcd(subset[j], subset[k]) ! = 1 ) :
flag = False
if (flag = = True ):
answer = max (answer, len (subset))
return answer
A = [ 2 , 3 , 13 , 5 , 14 , 6 , 7 , 11 ]
N = len (A)
print (largestSubset(A, N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int gcd( int a, int b)
{
if (a == 0)
return b;
if (b == 0)
return a;
if (a == b)
return a;
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
static int largestSubset( int []a, int n)
{
int answer = 0;
for ( int i = 1; i < (1 << n); i++)
{
List< int > subset = new List< int >();
for ( int j = 0; j < n; j++)
{
if ((i & (1 << j)) != 0)
subset.Add(a[j]);
}
int flag = 1;
for ( int j = 0; j < subset.Count; j++)
{
for ( int k = j + 1; k < subset.Count; k++)
{
if (gcd(( int )subset[j],
( int ) subset[k]) != 1)
flag = 0;
}
}
if (flag == 1)
answer = Math.Max(answer,
( int )subset.Count);
}
return answer;
}
public static void Main()
{
int []A = { 2, 3, 13, 5, 14, 6, 7, 11 };
int N = A.Length;
Console.WriteLine(largestSubset(A, N));
}
}
|
Javascript
<script>
function gcd(a, b)
{
if (a == 0)
return b;
if (b == 0)
return a;
if (a == b)
return a;
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
function largestSubset(a, n)
{
let answer = 0;
for (let i = 1; i < (1 << n); i++)
{
let subset = [];
for (let j = 0; j < n; j++)
{
if ((i & (1 << j)) != 0)
subset.push(a[j]);
}
let flag = 1;
for (let j = 0; j < subset.length; j++)
{
for (let k = j + 1; k < subset.length; k++)
{
if (gcd(subset[j], subset[k]) != 1)
flag = 0;
}
}
if (flag == 1)
answer = Math.max(answer, subset.length);
}
return answer;
}
let A = [ 2, 3, 13, 5, 14, 6, 7, 11 ];
let N = A.length;
document.write(largestSubset(A, N));
</script>
|
Efficient Approach:
The above method can be optimized and the approach depends on the fact that there are only 15 prime numbers in the first 50 natural numbers. So all the numbers in array will have prime factors among these 15 numbers only. We will use Bitmasking and Dynamic Programming to optimize the problem.
- Since there are 15 primes only, consider a 15-bit representation of every number where each bit is 1 if that index of prime is a factor of that number. We will index prime numbers by 0 indexing, which means 2 at 0th position 3 at index 1 and so on.
- An integer variable ‘mask‘ indicates the prime factors which have already occurred in the subset. If i’th bit is set in the mask, then i’th prime factor has occurred, otherwise not.
- At each step of recurrence relation, the element can either be included in the subset or cannot be included. If the element is not included in the subarray, then simply move to the next index. If it is included, change the mask by setting all the bits corresponding to the current element’s prime factors, ON in the mask. The current element can only be included if all of its prime factors have not occurred previously.
- This condition will be satisfied only if the bits corresponding to the current element’s digits in the mask are OFF.
If we draw the complete recursion tree, we can observe that many subproblems are being solved which were occurring again and again. So we use a table dp[][] such that for every index dp[i][j], i is the position of the element in the array, and j is the mask.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[5000][(1 << 10) + 5];
int getmask( int val)
{
int mask = 0;
int prime[15] = { 2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47 };
for ( int i = 0; i < 15; i++) {
if (val % prime[i] == 0) {
mask = mask | (1 << i);
}
}
return mask;
}
int calculate( int pos, int mask,
int a[], int n)
{
if (pos == n || mask == (1 << n - 1))
return 0;
if (dp[pos][mask] != -1)
return dp[pos][mask];
int size = 0;
size = max(size, calculate(pos + 1, mask, a, n));
if ((getmask(a[pos]) & mask) == 0) {
int new_mask = (mask | (getmask(a[pos])));
size = max(size, 1 + calculate(pos + 1, new_mask, a, n));
}
return dp[pos][mask] = size;
}
int largestSubset( int a[], int n)
{
memset (dp, -1, sizeof (dp));
return calculate(0, 0, a, n);
}
int main()
{
int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 };
int N = sizeof (A) / sizeof (A[0]);
cout << largestSubset(A, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int dp[][] = new int [ 5000 ][ 1029 ];
static int getmask( int val)
{
int mask = 0 ;
int prime[] = { 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 ,
23 , 29 , 31 , 37 , 41 , 43 , 47 };
for ( int i = 0 ; i < 15 ; i++)
{
if (val % prime[i] == 0 )
{
mask = mask | ( 1 << i);
}
}
return mask;
}
static int calculate( int pos, int mask,
int a[], int n)
{
if (pos == n ||
mask == ( int )( 1 << n - 1 ))
return 0 ;
if (dp[pos][mask] != - 1 )
return dp[pos][mask];
int size = 0 ;
size = Math.max(size, calculate(pos + 1 ,
mask, a, n));
if ((getmask(a[pos]) & mask) == 0 )
{
int new_mask = (mask | (getmask(a[pos])));
size = Math.max(size, 1 + calculate(pos + 1 ,
new_mask,
a, n));
}
return dp[pos][mask] = size;
}
static int largestSubset( int a[], int n)
{
for ( int i = 0 ; i < 5000 ; i++)
Arrays.fill(dp[i], - 1 );
return calculate( 0 , 0 , a, n);
}
public static void main(String args[])
{
int A[] = { 2 , 3 , 13 , 5 , 14 , 6 , 7 , 11 };
int N = A.length;
System.out.println(largestSubset(A, N));
}
}
|
Python
dp = [[ - 1 ] * (( 1 << 10 ) + 5 )] * 5000
def getmask(val):
mask = 0
prime = [ 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 ,
23 , 29 , 31 , 37 , 41 , 43 , 47 ]
for i in range ( 1 , 15 ):
if val % prime[i] = = 0 :
mask = mask | ( 1 << i)
return mask
def calculate(pos, mask, a, n):
if ((pos = = n) or (mask = = ( 1 << n - 1 ))):
return 0
if dp[pos][mask] ! = - 1 :
return dp[pos][mask]
size = 0
size = max (size, calculate(pos + 1 ,
mask, a, n))
if (getmask(a[pos]) & mask) = = 0 :
new_mask = (mask | (getmask(a[pos])))
size = max (size, 1 + calculate(pos + 1 ,
new_mask,
a, n))
dp[pos][mask] = size
return dp[pos][mask]
def largestSubset(A, n):
return calculate( 0 , 0 , A, n);
A = [ 2 , 3 , 13 , 5 , 14 , 6 , 7 , 11 ]
N = len (A)
print (largestSubset(A, N))
|
C#
using System;
class GFG{
static int [,] dp = new int [5000, 1029];
static int getmask( int val)
{
int mask = 0;
int []prime = { 2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47 };
for ( int i = 0; i < 15; i++)
{
if (val % prime[i] == 0)
{
mask = mask | (1 << i);
}
}
return mask;
}
static int calculate( int pos, int mask,
int []a, int n)
{
if (pos == n ||
mask == ( int )(1 << n - 1))
return 0;
if (dp[pos, mask] != -1)
return dp[pos, mask];
int size = 0;
size = Math.Max(size, calculate(pos + 1,
mask, a, n));
if ((getmask(a[pos]) & mask) == 0)
{
int new_mask = (mask | (getmask(a[pos])));
size = Math.Max(size, 1 + calculate(pos + 1,
new_mask,
a, n));
}
return dp[pos, mask] = size;
}
static int largestSubset( int []a, int n)
{
for ( int i = 0; i < 5000; i++)
{
for ( int j = 0; j < 1029; j++)
dp[i, j] = -1;
}
return calculate(0, 0, a, n);
}
public static void Main()
{
int []A = { 2, 3, 13, 5, 14, 6, 7, 11 };
int N = A.Length;
Console.WriteLine(largestSubset(A, N));
}
}
|
Javascript
<script>
var dp = Array.from(Array(5000), ()=>Array((1 << 10) + 5));
function getmask( val)
{
var mask = 0;
var prime = [2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47];
for ( var i = 0; i < 15; i++) {
if (val % prime[i] == 0) {
mask = mask | (1 << i);
}
}
return mask;
}
function calculate(pos, mask, a, n)
{
if (pos == n || mask == (1 << n - 1))
return 0;
if (dp[pos][mask] != -1)
return dp[pos][mask];
var size = 0;
size = Math.max(size, calculate(pos + 1, mask, a, n));
if ((getmask(a[pos]) & mask) == 0) {
var new_mask = (mask | (getmask(a[pos])));
size = Math.max(size,
1 + calculate(pos + 1, new_mask, a, n));
}
return dp[pos][mask] = size;
}
function largestSubset(a, n)
{
dp = Array.from(Array(5000),
()=>Array((1 << 10) + 5).fill(-1));
return calculate(0, 0, a, n);
}
var A = [2, 3, 13, 5, 14, 6, 7, 11 ];
var N = A.length;
document.write( largestSubset(A, N));
</script>
|
Time Complexity: O(N * 15 * 215)
Auxiliary Space: O(n * 2^n)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memorization(top-down) because memorization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Initialize a DP table “dp” with size (n+1) x (2^n) and set all its values to 0.
- Fill the DP table in a bottom-up manner:
a. For each position “pos” in the array “a” (from right to left), and for each mask value “mask” (from 0 to 2^n – 1), do the following:
b. If the current element “a[pos]” has no common factor with the numbers represented by the “mask” value, then compute the new mask “new_mask” by ORing the “mask” value with the “getmask(a[pos])” value.
c. Update the size of the subset for this position and mask by taking the maximum of:
- the subset size for the next position “pos+1” and the current mask value “mask”, and
- the subset size for the next position “pos+1” and the new mask value “new_mask” (if it is valid).
- Return the subset size stored in the DP table for position 0 and mask 0.
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int getmask( int val)
{
int mask = 0;
int prime[15] = { 2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47 };
for ( int i = 0; i < 15; i++) {
if (val % prime[i] == 0) {
mask = mask | (1 << i);
}
}
return mask;
}
int largestSubset( int a[], int n) {
int dp[n+1][(1<<10)+5];
for ( int i = 0; i <= n; i++) {
for ( int j = 0; j <= (1<<n)-1; j++) {
dp[i][j] = 0;
}
}
for ( int pos = n-1; pos >= 0; pos--) {
for ( int mask = 0; mask < (1<<n)-1; mask++) {
int size = dp[pos+1][mask];
if ((getmask(a[pos]) & mask) == 0) {
int new_mask = (mask | (getmask(a[pos])));
size = max(size, 1 + dp[pos+1][new_mask]);
}
dp[pos][mask] = size;
}
}
return dp[0][0];
}
int main()
{
int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 };
int N = sizeof (A) / sizeof (A[0]);
cout << largestSubset(A, N);
return 0;
}
|
Java
import java.io.*;
import java.lang.*;
import java.util.*;
class Main {
static int getmask( int val)
{
int mask = 0 ;
int [] prime = { 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 ,
23 , 29 , 31 , 37 , 41 , 43 , 47 };
for ( int i = 0 ; i < 15 ; i++) {
if (val % prime[i] == 0 ) {
mask = mask | ( 1 << i);
}
}
return mask;
}
static int largestSubset( int [] a, int n)
{
int [][] dp = new int [n + 1 ][( 1 << 10 ) + 5 ];
for ( int i = 0 ; i <= n; i++) {
for ( int j = 0 ; j <= ( 1 << n) - 1 ; j++) {
dp[i][j] = 0 ;
}
}
for ( int pos = n - 1 ; pos >= 0 ; pos--) {
for ( int mask = 0 ; mask < ( 1 << n) - 1 ;
mask++) {
int size = dp[pos + 1 ][mask];
if ((getmask(a[pos]) & mask) == 0 ) {
int new_mask
= (mask | (getmask(a[pos])));
size = Math.max(
size, 1 + dp[pos + 1 ][new_mask]);
}
dp[pos][mask] = size;
}
}
return dp[ 0 ][ 0 ];
}
public static void main(String[] args)
{
int [] A = { 2 , 3 , 13 , 5 , 14 , 6 , 7 , 11 };
int N = A.length;
System.out.println(largestSubset(A, N));
}
}
|
Python3
def getmask(val):
mask = 0
prime = [ 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 ,
23 , 29 , 31 , 37 , 41 , 43 , 47 ]
for i in range ( 15 ):
if val % prime[i] = = 0 :
mask = mask | ( 1 << i)
return mask
def largestSubset(a):
n = len (a)
dp = [[ 0 for j in range (( 1 << 10 ) + 5 )] for i in range (n + 1 )]
for pos in range (n - 1 , - 1 , - 1 ):
for mask in range (( 1 << n) - 1 ):
size = dp[pos + 1 ][mask]
if (getmask(a[pos]) & mask) = = 0 :
new_mask = (mask | (getmask(a[pos])))
size = max (size, 1 + dp[pos + 1 ][new_mask])
dp[pos][mask] = size
return dp[ 0 ][ 0 ]
if __name__ = = '__main__' :
A = [ 2 , 3 , 13 , 5 , 14 , 6 , 7 , 11 ]
print (largestSubset(A))
|
C#
using System;
public class GFG
{
static int GetMask( int val)
{
int mask = 0;
int [] prime = { 2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47 };
for ( int i = 0; i < 15; i++)
{
if (val % prime[i] == 0)
{
mask = mask | (1 << i);
}
}
return mask;
}
static int LargestSubset( int [] a, int n)
{
int [,] dp = new int [n+1, (1<<10)+5];
for ( int i = 0; i <= n; i++)
{
for ( int j = 0; j <= (1<<n)-1; j++)
{
dp[i, j] = 0;
}
}
for ( int pos = n-1; pos >= 0; pos--)
{
for ( int mask = 0; mask < (1<<n)-1; mask++)
{
int size = dp[pos+1, mask];
if ((GetMask(a[pos]) & mask) == 0)
{
int new_mask = (mask | (GetMask(a[pos])));
size = Math.Max(size, 1 + dp[pos+1, new_mask]);
}
dp[pos, mask] = size;
}
}
return dp[0, 0];
}
public static void Main()
{
int [] A = { 2, 3, 13, 5, 14, 6, 7, 11 };
int N = A.Length;
Console.WriteLine(LargestSubset(A, N));
}
}
|
Javascript
function getmask(val) {
let mask = 0;
const prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];
for (let i = 0; i < 15; i++) {
if (val % prime[i] === 0) {
mask = mask | (1 << i);
}
}
return mask;
}
function largestSubset(a) {
const n = a.length;
const dp = Array.from({ length: n + 1 }, () => new Array((1 << 10) + 5).fill(0));
for (let pos = n - 1; pos >= 0; pos--) {
for (let mask = (1 << n) - 2; mask >= 0; mask--) {
let size = dp[pos + 1][mask];
if ((getmask(a[pos]) & mask) === 0) {
const new_mask = mask | getmask(a[pos]);
size = Math.max(size, 1 + dp[pos + 1][new_mask]);
}
dp[pos][mask] = size;
}
}
return dp[0][0];
}
const A = [2, 3, 13, 5, 14, 6, 7, 11];
console.log(largestSubset(A));
|
Time Complexity: O(n * 2^n)
Auxiliary Space: O(n * 2^n)
Last Updated :
11 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...