Count number of sub-sequences with GCD 1
Last Updated :
14 Sep, 2022
Given an array of N numbers, the task is to count the number of subsequences that have gcd equal to 1.
Examples:
Input: a[] = {3, 4, 8, 16}
Output: 7
The subsequences are:
{3, 4}, {3, 8}, {3, 16}, {3, 4, 8},
{3, 4, 16}, {3, 8, 16}, {3, 4, 8, 16}
Input: a[] = {1, 2, 4}
Output: 4
A simple solution is to generate all subsequences or subsets. For every subsequence, check if its GCD is 1 or not. If 1, increment the result.
When we have values in the array (say all smaller than 1000), we can optimize the above solution as we know that number of possible GCDs would be small. We modify the recursive subset generation algorithm was considering two cases for every element, we either include or exclude it. We keep track of the current GCD and if we have already counted for this GCD, we return the count. So when we are considering a subset, some GCDs would appear again and again. Therefore the problem can be solved using Dynamic Programming. Given below are the steps to solve the above problem:
- Start from every index and call the recursive function by taking the index element.
- In the recursive function, we iterate till we reach N.
- The two recursive calls will be based on whether we take the index element or not.
- The base case will be to return 1 if we have reached the end and the gcd till now is 1.
- Two recursive calls will be func(ind+1, gcd(a[i], prevgcd)) and func(ind+1, prevgcd)
- The overlapping subproblems can be avoided by using the memoization technique.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
int gcd( int a, int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
int func( int ind, int g, int dp[][MAX], int n, int a[])
{
if (ind == n) {
if (g == 1)
return 1;
else
return 0;
}
if (dp[ind][g] != -1)
return dp[ind][g];
int ans = func(ind + 1, g, dp, n, a)
+ func(ind + 1, gcd(a[ind], g), dp, n, a);
return dp[ind][g] = ans;
}
int countSubsequences( int a[], int n)
{
int dp[n][MAX];
memset (dp, -1, sizeof dp);
int count = 0;
for ( int i = 0; i < n; i++)
count += func(i + 1, a[i], dp, n, a);
return count;
}
int main()
{
int a[] = { 3, 4, 8, 16 };
int n = sizeof (a) / sizeof (a[0]);
cout << countSubsequences(a, n);
return 0;
}
|
Java
class GFG
{
static final int MAX = 1000 ;
static int gcd( int a, int b)
{
if (a == 0 )
return b;
return gcd(b % a, a);
}
static int func( int ind, int g, int dp[][],
int n, int a[])
{
if (ind == n)
{
if (g == 1 )
return 1 ;
else
return 0 ;
}
if (dp[ind][g] != - 1 )
return dp[ind][g];
int ans = func(ind + 1 , g, dp, n, a)
+ func(ind + 1 , gcd(a[ind], g), dp, n, a);
return dp[ind][g] = ans;
}
static int countSubsequences( int a[], int n)
{
int dp[][] = new int [n][MAX];
for ( int i = 0 ; i < n; i++)
for ( int j = 0 ; j < MAX; j++)
dp[i][j] = - 1 ;
int count = 0 ;
for ( int i = 0 ; i < n; i++)
count += func(i + 1 , a[i], dp, n, a);
return count;
}
public static void main(String args[])
{
int a[] = { 3 , 4 , 8 , 16 };
int n = a.length;
System.out.println(countSubsequences(a, n));
}
}
|
Python3
MAX = 1000
def gcd(a, b):
if (a = = 0 ):
return b
return gcd(b % a, a)
def func(ind, g, dp, n, a):
if (ind = = n):
if (g = = 1 ):
return 1
else :
return 0
if (dp[ind][g] ! = - 1 ):
return dp[ind][g]
ans = (func(ind + 1 , g, dp, n, a) +
func(ind + 1 , gcd(a[ind], g),
dp, n, a))
dp[ind][g] = ans
return dp[ind][g]
def countSubsequences(a, n):
dp = [[ - 1 for i in range ( MAX )]
for i in range (n)]
count = 0
for i in range (n):
count + = func(i + 1 , a[i], dp, n, a)
return count
a = [ 3 , 4 , 8 , 16 ]
n = len (a)
print (countSubsequences(a, n))
|
C#
using System;
class GFG
{
static int gcd( int a, int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
static int func( int ind, int g, int [][] dp,
int n, int [] a)
{
if (ind == n)
{
if (g == 1)
return 1;
else
return 0;
}
if (dp[ind][g] != -1)
return dp[ind][g];
int ans = func(ind + 1, g, dp, n, a)
+ func(ind + 1, gcd(a[ind], g), dp, n, a);
return dp[ind][g] = ans;
}
static int countSubsequences( int [] a, int n)
{
int [][] dp = new int [n][];
for ( int i = 0; i < n; i++)
for ( int j = 0; j < 1000; j++)
dp[i][j] = -1;
int count = 0;
for ( int i = 0; i < n; i++)
count += func(i + 1, a[i], dp, n, a);
return count;
}
public static void Main()
{
int [] a = { 3, 4, 8, 16 };
int n = 4;
int x = countSubsequences(a, n);
Console.Write(x);
}
}
|
PHP
<?php
$GLOBALS [ 'MAX' ] = 1000;
function gcd( $a , $b )
{
if ( $a == 0)
return $b ;
return gcd( $b % $a , $a );
}
function func( $ind , $g , $dp , $n , $a )
{
if ( $ind == $n )
{
if ( $g == 1)
return 1;
else
return 0;
}
if ( $dp [ $ind ][ $g ] != -1)
return $dp [ $ind ][ $g ];
$ans = func( $ind + 1, $g , $dp , $n , $a ) +
func( $ind + 1, gcd( $a [ $ind ], $g ),
$dp , $n , $a );
$dp [ $ind ][ $g ] = $ans ;
return $dp [ $ind ][ $g ] ;
}
function countSubsequences( $a , $n )
{
$dp = array ( array ()) ;
for ( $i = 0 ; $i < $n ; $i ++)
for ( $j = 0;
$j < $GLOBALS [ 'MAX' ]; $j ++)
$dp [ $i ][ $j ] = -1 ;
$count = 0;
for ( $i = 0; $i < $n ; $i ++)
$count += func( $i + 1, $a [ $i ],
$dp , $n , $a );
return $count ;
}
$a = array (3, 4, 8, 16);
$n = sizeof( $a ) ;
echo countSubsequences( $a , $n );
?>
|
Javascript
<script>
var MAX = 1000;
function gcd(a , b) {
if (a == 0)
return b;
return gcd(b % a, a);
}
function func(ind , g , dp , n , a) {
if (ind == n) {
if (g == 1)
return 1;
else
return 0;
}
if (dp[ind][g] != -1)
return dp[ind][g];
var ans = func(ind + 1, g, dp, n, a) +
func(ind + 1, gcd(a[ind], g), dp, n, a);
return dp[ind][g] = ans;
}
function countSubsequences(a , n) {
var dp = Array(n).fill().map(()=>Array(MAX).fill(0));
for (i = 0; i < n; i++)
for (j = 0; j < MAX; j++)
dp[i][j] = -1;
var count = 0;
for (i = 0; i < n; i++)
count += func(i + 1, a[i], dp, n, a);
return count;
}
var a = [ 3, 4, 8, 16 ];
var n = a.length;
document.write(countSubsequences(a, n));
</script>
|
Complexity Analysis:
- Time Complexity: O(logN*N2), as we are recursively calling the function two times but we are using memorization and the GCD function will cost O(logN). Where N is the number of elements in the array.
- Auxiliary Space: O(N*1000), as we are using extra space for the DP matrix. Where N is the number of elements in the array.
Alternate Solution: Count the number of subsets of a set with GCD equal to a given number
Dynamic programming approach to this problem without memoization:
Basically, the approach will be making a 2d matrix in which i coordinate will be the position of elements of the given array and the j coordinate will be numbers from 0 to 100 ie. gcd can vary from 0 to 100 if array elements are not enough large. we will iterate on the given array and the 2d matrix will store information that till ith position that how many subsequences are there having gcd vary from 1 to 100. later on, we will add dp[i][1] to get all subsequences having gcd as 1.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int gcd( int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
int countSubsequences( int arr[], int n)
{
long long int dp[n][101] = {0};
for ( int i = 0; i < n; i++)
{
dp[i][arr[i]] = 1;
for ( int j = i - 1; j >= 0; j--)
{
if (arr[j] < arr[i])
{
for ( int k = 0; k <= 100; k++)
{
int GCD = gcd(arr[i], k);
dp[i][GCD] = dp[i][GCD] +
dp[j][k];
}
}
}
}
long long int sum = 0;
for ( int i = 0; i < n; i++)
{
sum=(sum + dp[i][1]);
}
return sum;
}
int main()
{
int a[] = { 3, 4, 8, 16 };
int n = sizeof (a) / sizeof (a[0]);
cout << countSubsequences(a, n);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int gcd( int a, int b)
{
if (b == 0 )
return a;
return gcd(b, a % b);
}
static long countSubsequences( int arr[],
int n)
{
long dp[][] = new long [n][ 101 ];
for ( int i = 0 ; i < n; i++)
{
for ( int j = 0 ; j < 101 ; j++)
{
dp[i][j] = 0 ;
}
}
for ( int i = 0 ; i < n; i++)
{
dp[i][arr[i]] = 1 ;
for ( int j = i - 1 ; j >= 0 ; j--)
{
if (arr[j] < arr[i])
{
for ( int k = 0 ; k <= 100 ; k++)
{
int GCD = gcd(arr[i], k);
dp[i][GCD] = dp[i][GCD] +
dp[j][k];
}
}
}
}
long sum = 0 ;
for ( int i = 0 ; i < n; i++)
{
sum = (sum + dp[i][ 1 ]);
}
return sum;
}
public static void main(String args[])
{
int a[] = { 3 , 4 , 8 , 16 };
int n = a.length;
System.out.println(countSubsequences(a, n));
}
}
|
Python3
def gcd(a, b):
if (b = = 0 ):
return a;
return gcd(b, a % b);
def countSubsequences(arr, n):
dp = [[ 0 for i in range ( 101 )] for j in range (n)]
for i in range (n):
dp[i][arr[i]] = 1 ;
for j in range (i - 1 , - 1 , - 1 ):
if (arr[j] < arr[i]):
for k in range ( 101 ):
GCD = gcd(arr[i], k);
dp[i][GCD] = dp[i][GCD] + dp[j][k];
sum = 0 ;
for i in range (n):
sum = ( sum + dp[i][ 1 ]);
return sum ;
if __name__ = = '__main__' :
a = [ 3 , 4 , 8 , 16 ]
n = len (a)
print (countSubsequences(a,n))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
static int gcd( int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
static long countSubsequences( int []arr,
int n)
{
long [,]dp = new long [n, 101];
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < 101; j++)
{
dp[i, j] = 0;
}
}
for ( int i = 0; i < n; i++)
{
dp[i, arr[i]] = 1;
for ( int j = i - 1; j >= 0; j--)
{
if (arr[j] < arr[i])
{
for ( int k = 0; k <= 100; k++)
{
int GCD = gcd(arr[i], k);
dp[i, GCD] = dp[i, GCD] +
dp[j, k];
}
}
}
}
long sum = 0;
for ( int i = 0; i < n; i++)
{
sum = (sum + dp[i, 1]);
}
return sum;
}
public static void Main( string []args)
{
int []a = { 3, 4, 8, 16 };
int n = a.Length;
Console.WriteLine(countSubsequences(a, n));
}
}
|
Javascript
<script>
function gcd(a , b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
function countSubsequences(arr , n) {
var dp = Array(n).fill().map(()=>Array(101).fill(0));
for (i = 0; i < n; i++) {
for (j = 0; j < 101; j++) {
dp[i][j] = 0;
}
}
for (i = 0; i < n; i++) {
dp[i][arr[i]] = 1;
for (j = i - 1; j >= 0; j--) {
if (arr[j] < arr[i]) {
for (k = 0; k <= 100; k++) {
var GCD = gcd(arr[i], k);
dp[i][GCD] = dp[i][GCD] + dp[j][k];
}
}
}
}
var sum = 0;
for (i = 0; i < n; i++) {
sum = (sum + dp[i][1]);
}
return sum;
}
var a = [ 3, 4, 8, 16 ];
var n = a.length;
document.write(countSubsequences(a, n));
</script>
|
Complexity Analysis:
- Time Complexity: O(100*logN*N2), as we are using nested loops and the GCD function will cost O(logN). Where N is the number of elements in the array.
- Auxiliary Space: O(N*100), as we are using extra space for the DP matrix. Where N is the number of elements in the array.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...