Minimum length of subsequence having unit GCD - GeeksforGeeks

22 Jun, 2021
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 like 2.
Input: arr[] = {2, 4}Output: -1Explanation:GCD of 2, 4 = 2 
Naive Approach: The idea is to generate all possible subsequences of the given array and print the length of that subsequence whose GCD is unity and has a minimum length. If none of the sub-sequences 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: 
Two numbers will have their GCD equal to one only when their prime factors are different.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, which is 29, it will be greater than 10^9.
Two numbers will have their GCD equal to one only when their prime factors are different.
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, which is 29, it will be greater than 10^9.
Follow the steps below to solve the problem:
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 and 3. This can be expressed in binary as 11 (Ignoring the preceding zeroes), meaning two prime factors are there for this number.For every number in the input array, check if any other number has the corresponding bit set or not. This could be achieved using Bitwise AND operation. The resultant of this operation is another state of our solution space.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.Every state uses dynamic programming to store the shortest way to reach that state.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”.
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 and 3. This can be expressed in binary as 11 (Ignoring the preceding zeroes), meaning two prime factors are there for this number.
For every number in the input array, check if any other number has the corresponding bit set or not. This could be achieved using Bitwise AND operation. The resultant of this operation is another state of our solution space.
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.
Every state uses dynamic programming to store the shortest way to reach that state.
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++
Java
Python3
C#
Javascript
// C++ program for the above approach#include <bits/stdc++.h>using namespace std; // Function that finds the prime// factors of a numbervector<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// subsequencevoid 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 subsequencevoid 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 codeint main(){    // Given array arr[]    vector<int> arr = { 2, 6, 12, 3 };         // Function Call    printMinimumLength(arr);    return 0;} // This code is contributed by divyeshrabadiya07
// Java program for the above approachimport 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);    }}
# Python3 program for the above approach # Function that finds the prime# factors of a numberdef 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# subsequencedef 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 subsequencedef 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 Codeif __name__ == '__main__':         # Given array arr[]    arr = [ 2, 6, 12, 3 ]     # Function Call    printMinimumLength(arr) # This code is contributed by bgangwar59
// C# program for// the above approachusing System;class GFG{ // Function that finds the prime// factors of a numberprivate 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// subsequenceprivate 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 subsequenceprivate 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 Codepublic 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
<script>// Javascript program for the above approach // Function that finds the prime// factors of a numberfunction findPrimeFactors(n){    // To store the prime factor    let primeFactors = new Array(9).fill(0);     let 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 (let 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;         let PrimeFactors = new Array(j);         for(let i = 0; i < j; i++)    {        PrimeFactors[i] = primeFactors[i];    }         return PrimeFactors;} // Function that finds the shortest// subsequencefunction findShortestSubsequence(dp, a, index, primeFactors){    let n = a.length;     for (let j = index; j < n; j++) {        let bitmask = 0;         for (let 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 (let 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 subsequencefunction prletMinimumLength(a){    let Min = a.length + 1;     for (let i = 0; i < a.length - 1; i++) {         // Find the prime factors of        // the first number        let primeFactors = findPrimeFactors(a[i]);         let n = primeFactors.length;             // Initialize the array with        // maximum steps, size of the        // array + 1 for instance        let dp = new Array(1 << n);         for(let 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        let 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))        document.write(-1 + "<br>");     // Else print the length    else        document.write(Min + "<br>");} // Driver code     // Given array arr[]    let arr = [ 2, 6, 12, 3 ];         // Function Call    prletMinimumLength(arr); // This code is contributed by _saurabh_jaiswal</script>
2
Time Complexity: O(N2)Auxiliary Space: O(1) 
jithin
Rajput-Ji
bgangwar59
divyeshrabadiya07
gfgking
khushboogoyal499
Algorithms-Dynamic Programming
Bitwise-AND
GCD-LCM
subsequence
Arrays
Bit Magic
Dynamic Programming
Mathematical
Arrays
Dynamic Programming
Mathematical
Bit Magic
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Next Greater Element
Window Sliding Technique
Count pairs with given sum
Program to find sum of elements in a given array
Reversal algorithm for array rotation
Bitwise Operators in C/C++
Left Shift and Right Shift Operators in C/C++
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Count set bits in an integer
Cyclic Redundancy Check and Modulo-2 Division