Skip to content
Related Articles

Related Articles

Minimum length of subsequence having unit GCD
  • Last Updated : 14 Dec, 2020

Given an array arr[] of N positive integers. The task is to find the length of the shortest sub-sequence such that the GCD of the subsequence is 1. If none of the sub-sequence has GCD 1, then print “-1“. 

Examples:

Input: arr[] = {2, 6, 12, 3}
Output: 2  
Explanation:
The GCD of 2, 3 = 1, which is the smallest length of subsequence as 2.

Input: arr[] = {2, 4}
Output: -1
Explanation:
GCD of 2, 4 = 2 

Naive Approach: The idea is to generate all possible subsequence of the given array and print the length of that subsequence whose GCD is unity and have a minimum length. If none of the sub-sequence has GCD 1, then print “-1“.



Time Complexity: O(2N
Auxiliary Space: O(1)  

Efficient Approach: There are 2 key observations for solving this problem: 

  1. Two numbers will have their GCD equal to one only when their prime factors are different.
  2. Any positive number which is less than 109 can have a maximum of 9 prime factors. 
    For Example 2×3×5×7×11×13×17×19×23 = 22, 30, 92, 870. If we multiply this number by the next prime number that is 29, it will be greater than 10^9.

Follow the steps below to solve the problem:

  1. Express the numbers as the product of its prime factors. Since we have a maximum of 9 prime factors, we can use the concept of Bitmask to store the state of the number. 
    For Example, prime factors of 12 are 2, 3. This can be expressed in binary as 11 (Ignoring the preceding zeroes) meaning two prime factors are there for this number.
  2. For every number in the input array, check if any other number has the corresponding bits set or not. This could be achieved using Bitwise AND operation. The resultant of this operation is another state of our solution space.
  3. Now use the concept of Dynamic Programming to memorize the states. The idea is to use an array to store the states of the solution space. This works since only 9 bits could be set a time, and an array of size 1024 could capture all the states of the solution space.
  4. For every state use dynamic programming to store the shortest way to reach that state.
  5. If the Bitwise AND of any two states is equal to 0, then the GCD is equal to one, i.e., if there is a possibility to reach state 0 from the current state, then it will have the minimum length sub-sequence and print that length otherwise print “-1”.

Below is the implementation of the above approach: 

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function that finds the prime
// factors of a number
vector<int> findPrimeFactors(int n)
{
    // To store the prime factor
    vector<int> primeFactors(9, 0);
 
    int j = 0;
 
    // 2s that divide n
    if (n % 2 == 0) {
        primeFactors[j++] = 2;
        while (n % 2 == 0)
            n >>= 1;
    }
 
    // N must be odd at this point
    // Skip one element
    for (int i = 3;
         i * i <= n; i += 2) {
 
        if (n % i == 0) {
 
            // Update the prime factor
            primeFactors[j++] = i;
            while (n % i == 0)
                n /= i;
        }
    }
 
    // If n is a prime number
    // greater than 2
    if (n > 2)
        primeFactors[j++] = n;
     
    vector<int> PrimeFactors(j);
     
    for(int i = 0; i < j; i++)
    {
        PrimeFactors[i] = primeFactors[i];
    }
     
    return PrimeFactors;
}
 
// Function that finds the shortest
// subsequence
void findShortestSubsequence(vector<int> &dp, vector<int> a,
                        int index, vector<int> primeFactors)
{
    int n = a.size();
 
    for (int j = index; j < n; j++) {
        int bitmask = 0;
 
        for (int p = 0;
             p < primeFactors.size(); p++) {
 
            // Check if the prime factor
            // of first number, is also
            // the prime factor of the
            // rest numbers in array
            if ((a[j] % primeFactors[p]) == 0) {
 
                // Set corresponding bit
                // of prime factor to 1,
                // it means both these
                // numbers have the
                // same prime factor
                bitmask ^= (1 << p);
            }
        }
 
        for (int i = 0; i < dp.size(); i++) {
 
            // If no states encountered
            // so far continue for this
            // combination of bits
            if (dp[i] == n + 1)
                continue;
 
            // Update this state with
            // minimum ways to reach
            // this state
            dp[bitmask & i]
                = min(dp[bitmask & i],
                           dp[i] + 1);
        }
    }
}
 
// Function that print the minimum
// length of subsequence
void printMinimumLength(vector<int> a)
{
    int Min = a.size() + 1;
 
    for (int i = 0; i < a.size() - 1; i++) {
 
        // Find the prime factors of
        // the first number
        vector<int> primeFactors
            = findPrimeFactors(a[i]);
 
        int n = primeFactors.size();
     
        // Initialize the array with
        // maximum steps, size of the
        // array + 1 for instance
        vector<int> dp(1 << n, a.size() + 1);
 
        // Express the prime factors
        // in bit representation
 
        // Total number of set bits is
        // equal to the total number
        // of prime factors
        int setBits = (1 << n) - 1;
 
        // Indicates there is one
        // way to reach the number
        // under consideration
        dp[setBits] = 1;
        findShortestSubsequence(dp, a, i + 1,
                                primeFactors);
 
        // State 0 corresponds
        // to gcd of 1
        Min = min(dp[0], Min);
    }
 
    // If not found such subsequence
    // then print "-1"
    if (Min == (a.size() + 1))
        cout << -1 << endl;
 
    // Else print the length
    else
        cout << Min << endl;
}
 
// Driver code
int main()
{
    // Given array arr[]
    vector<int> arr = { 2, 6, 12, 3 };
     
    // Function Call
    printMinimumLength(arr);
    return 0;
}
 
// This code is contributed by divyeshrabadiya07

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function that finds the prime
    // factors of a number
    private static int[] findPrimeFactors(int n)
    {
        // To store the prime factor
        int[] primeFactors = new int[9];
 
        int j = 0;
 
        // 2s that divide n
        if (n % 2 == 0) {
            primeFactors[j++] = 2;
            while (n % 2 == 0)
                n >>= 1;
        }
 
        // N must be odd at this point
        // Skip one element
        for (int i = 3;
             i * i <= n; i += 2) {
 
            if (n % i == 0) {
 
                // Update the prime factor
                primeFactors[j++] = i;
                while (n % i == 0)
                    n /= i;
            }
        }
 
        // If n is a prime number
        // greater than 2
        if (n > 2)
            primeFactors[j++] = n;
 
        return Arrays.copyOfRange(primeFactors, 0, j);
    }
 
    // Function that finds the shortest
    // subsequence
    private static void
    findShortestSubsequence(int[] dp, int[] a,
                            int index,
                            int[] primeFactors)
    {
        int n = a.length;
 
        for (int j = index; j < n; j++) {
            int bitmask = 0;
 
            for (int p = 0;
                 p < primeFactors.length; p++) {
 
                // Check if the prime factor
                // of first number, is also
                // the prime factor of the
                // rest numbers in array
                if (a[j] % primeFactors[p] == 0) {
 
                    // Set corresponding bit
                    // of prime factor to 1,
                    // it means both these
                    // numbers have the
                    // same prime factor
                    bitmask ^= (1 << p);
                }
            }
 
            for (int i = 0;
                 i < dp.length; i++) {
 
                // If no states encountered
                // so far continue for this
                // combination of bits
                if (dp[i] == n + 1)
                    continue;
 
                // Update this state with
                // minimum ways to reach
                // this state
                dp[bitmask & i]
                    = Math.min(dp[bitmask & i],
                               dp[i] + 1);
            }
        }
    }
 
    // Function that print the minimum
    // length of subsequence
    private static void
    printMinimumLength(int[] a)
    {
        int min = a.length + 1;
 
        for (int i = 0;
             i < a.length - 1; i++) {
 
            // Find the prime factors of
            // the first number
            int[] primeFactors
                = findPrimeFactors(a[i]);
 
            int n = primeFactors.length;
 
            int[] dp = new int[1 << n];
 
            // Initialize the array with
            // maximum steps, size of the
            // array + 1 for instance
            Arrays.fill(dp, a.length + 1);
 
            // Express the prime factors
            // in bit representation
 
            // Total number of set bits is
            // equal to the total number
            // of prime factors
            int setBits = (1 << n) - 1;
 
            // Indicates there is one
            // way to reach the number
            // under consideration
            dp[setBits] = 1;
            findShortestSubsequence(dp, a, i + 1,
                                    primeFactors);
 
            // State 0 corresponds
            // to gcd of 1
            min = Math.min(dp[0], min);
        }
 
        // If not found such subsequence
        // then print "-1"
        if (min == a.length + 1)
            System.out.println(-1);
 
        // Else print the length
        else
            System.out.println(min);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given array arr[]
        int[] arr = { 2, 6, 12, 3 };
 
        // Function Call
        printMinimumLength(arr);
    }
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
 
# Function that finds the prime
# factors of a number
def findPrimeFactors(n):
     
    # To store the prime factor
    primeFactors = [0 for i in range(9)]
 
    j = 0
 
    # 2s that divide n
    if (n % 2 == 0):
        primeFactors[j] = 2
        j += 1
         
        while (n % 2 == 0):
            n >>= 1
 
    # N must be odd at this point
    # Skip one element
    i = 3
    while (i * i <= n):
        if (n % i == 0):
             
            # Update the prime factor
            primeFactors[j] = i
            j += 1
             
            while(n % i == 0):
                n //= i
                 
        i += 2
 
    # If n is a prime number
    # greater than 2
    if (n > 2):
        primeFactors[j] = n
        j += 1
 
    for i in range(0, j + 1):
        primeFactors[i] = 0
         
    return primeFactors
 
# Function that finds the shortest
# subsequence
def findShortestSubsequence(dp, a, index,
                            primeFactors):
    n = len(a)
 
    for j in range(index, n):
        bitmask = 0
 
        for p in range(len(primeFactors)):
             
            # Check if the prime factor
            # of first number, is also
            # the prime factor of the
            # rest numbers in array
            if (primeFactors[p] != 0 and
                a[j] % primeFactors[p] == 0):
                     
                # Set corresponding bit
                # of prime factor to 1,
                # it means both these
                # numbers have the
                # same prime factor
                bitmask ^= (1 << p)
 
        for i in range(len(dp)):
             
            # If no states encountered
            # so far continue for this
            # combination of bits
            if (dp[i] == n + 1):
                continue
 
            # Update this state with
            # minimum ways to reach
            # this state
            dp[bitmask & i] = min(dp[bitmask & i],
                                  dp[i] + 1)
 
# Function that print the minimum
# length of subsequence
def printMinimumLength(a):
     
    mn = len(a) + 1
 
    for i in range(len(a) - 1):
 
        # Find the prime factors of
        # the first number
        primeFactors = findPrimeFactors(a[i])
 
        n = len(primeFactors)
 
        dp = [0 for i in range(1 << n)]
 
        # Initialize the array with
        # maximum steps, size of the
        # array + 1 for instance
        dp = [len(a) + 1 for i in range(len(dp))]
 
        # Express the prime factors
        # in bit representation
 
        # Total number of set bits is
        # equal to the total number
        # of prime factors
        setBits = (1 << n) - 1
 
        # Indicates there is one
        # way to reach the number
        # under consideration
        dp[setBits] = 1
         
        findShortestSubsequence(dp, a, i + 1,
                                primeFactors)
 
        # State 0 corresponds
        # to gcd of 1
        mn = min(dp[0], mn)
 
    # If not found such subsequence
    # then print "-1"
    if (mn == len(a) + 1):
        print(-1)
 
    # Else print the length
    else:
        print(mn)
 
# Driver Code
if __name__ == '__main__':
     
    # Given array arr[]
    arr = [ 2, 6, 12, 3 ]
 
    # Function Call
    printMinimumLength(arr)
 
# This code is contributed by bgangwar59

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for
// the above approach
using System;
class GFG{
 
// Function that finds the prime
// factors of a number
private static int[] findPrimeFactors(int n)
{
  // To store the prime factor
  int[] primeFactors = new int[9];
 
  int j = 0;
 
  // 2s that divide n
  if (n % 2 == 0)
  {
    primeFactors[j++] = 2;
    while (n % 2 == 0)
      n >>= 1;
  }
 
  // N must be odd at this point
  // Skip one element
  for (int i = 3;
           i * i <= n; i += 2)
  {
    if (n % i == 0)
    {
      // Update the prime factor
      primeFactors[j++] = i;
      while (n % i == 0)
        n /= i;
    }
  }
 
  // If n is a prime number
  // greater than 2
  if (n > 2)
    primeFactors[j++] = n;
   
  int []temp = new int[j];
  Array.Copy(primeFactors, temp, j);
  return temp;
}
 
// Function that finds the shortest
// subsequence
private static void findShortestSubsequence(int[] dp, int[] a,
                                            int index,
                                            int[] primeFactors)
{
  int n = a.Length;
 
  for (int j = index; j < n; j++)
  {
    int bitmask = 0;
 
    for (int p = 0;
             p < primeFactors.Length; p++)
    {
      // Check if the prime factor
      // of first number, is also
      // the prime factor of the
      // rest numbers in array
      if (a[j] % primeFactors[p] == 0)
      {
        // Set corresponding bit
        // of prime factor to 1,
        // it means both these
        // numbers have the
        // same prime factor
        bitmask ^= (1 << p);
      }
    }
 
    for (int i = 0;
             i < dp.Length; i++)
    {
      // If no states encountered
      // so far continue for this
      // combination of bits
      if (dp[i] == n + 1)
        continue;
 
      // Update this state with
      // minimum ways to reach
      // this state
      dp[bitmask & i] = Math.Min(dp[bitmask & i],
                                 dp[i] + 1);
    }
  }
}
 
// Function that print the minimum
// length of subsequence
private static void printMinimumLength(int[] a)
{
  int min = a.Length + 1;
 
  for (int i = 0;
           i < a.Length - 1; i++)
  {
    // Find the prime factors of
    // the first number
    int[] primeFactors = findPrimeFactors(a[i]);
 
    int n = primeFactors.Length;
 
    int[] dp = new int[1 << n];
 
    // Initialize the array with
    // maximum steps, size of the
    // array + 1 for instance
    for(i = 0; i < dp.Length; i++)
      dp[i] = a.Length + 1;
 
    // Express the prime factors
    // in bit representation
 
    // Total number of set bits is
    // equal to the total number
    // of prime factors
    int setBits = (1 << n) - 1;
 
    // Indicates there is one
    // way to reach the number
    // under consideration
    dp[setBits] = 1;
    findShortestSubsequence(dp, a, i + 1,
                            primeFactors);
 
    // State 0 corresponds
    // to gcd of 1
    min = Math.Min(dp[0], min);
  }
 
  // If not found such subsequence
  // then print "-1"
  if (min == a.Length + 1)
    Console.WriteLine(-1);
 
  // Else print the length
  else
    Console.WriteLine(min);
}
 
// Driver Code
public static void Main(String[] args)
{
  // Given array []arr
  int[] arr = {2, 6, 12, 3};
 
  // Function Call
  printMinimumLength(arr);
}
}
 
// This code is contributed by Rajput-Ji

chevron_right


Output

2

Time Complexity: O(N2)
Auxiliary Space: O(1) 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :