用 GCD 1 计算子序列的数量
给定一个包含 N 个数字的数组,任务是计算 gcd 等于 1 的子序列的数量。
例子:
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
一个简单的解决方案是生成所有子序列或子集。对于每个子序列,检查其 GCD 是否为 1。如果为 1,则增加结果。
当我们在数组中有值时(比如说都小于 1000),我们可以优化上述解决方案,因为我们知道可能的 GCD 数量会很少。我们修改了递归子集生成算法,其中考虑每个元素的两种情况,我们要么包含它,要么排除它。我们跟踪当前的 GCD,如果我们已经计算了这个 GCD,我们返回计数。因此,当我们考虑一个子集时,一些 GCD 会一次又一次地出现。所以这个问题可以用动态规划来解决。下面给出解决上述问题的步骤:
- 从每个索引开始,通过获取索引元素调用递归函数。
- 在递归函数中,我们迭代直到达到 N。
- 这两个递归调用将基于我们是否采用索引元素。
- 如果我们已经到达终点并且到目前为止的 gcd 为 1,则基本情况将返回 1。
- 两个递归调用将是 func(ind+1, gcd(a[i], prevgcd)) 和 func(ind+1, prevgcd)
- 通过使用记忆技术可以避免重叠子问题。
下面是上述方法的实现:
C++
// C++ program to find the number
// of subsequences with gcd 1
#include
using namespace std;
#define MAX 1000
int gcd(int a, int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
// Recursive function to calculate the number
// of subsequences with gcd 1 starting with
// particular index
int func(int ind, int g, int dp[][MAX], int n, int a[])
{
// Base case
if (ind == n) {
if (g == 1)
return 1;
else
return 0;
}
// If already visited
if (dp[ind][g] != -1)
return dp[ind][g];
// Either we take or we do not
int ans = func(ind + 1, g, dp, n, a)
+ func(ind + 1, gcd(a[ind], g), dp, n, a);
// Return the answer
return dp[ind][g] = ans;
}
// Function to return the number of subsequences
int countSubsequences(int a[], int n)
{
// Hash table to memoize
int dp[n][MAX];
memset(dp, -1, sizeof dp);
// Count the number of subsequences
int count = 0;
// Count for every subsequence
for (int i = 0; i < n; i++)
count += func(i + 1, a[i], dp, n, a);
return count;
}
// Driver Code
int main()
{
int a[] = { 3, 4, 8, 16 };
int n = sizeof(a) / sizeof(a[0]);
cout << countSubsequences(a, n);
return 0;
}
Java
// Java program to find the number
// of subsequences with gcd 1
class GFG
{
static final int MAX = 1000;
static int gcd(int a, int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
// Recursive function to calculate the number
// of subsequences with gcd 1 starting with
// particular index
static int func(int ind, int g, int dp[][],
int n, int a[])
{
// Base case
if (ind == n)
{
if (g == 1)
return 1;
else
return 0;
}
// If already visited
if (dp[ind][g] != -1)
return dp[ind][g];
// Either we take or we do not
int ans = func(ind + 1, g, dp, n, a)
+ func(ind + 1, gcd(a[ind], g), dp, n, a);
// Return the answer
return dp[ind][g] = ans;
}
// Function to return the
// number of subsequences
static int countSubsequences(int a[], int n)
{
// Hash table to memoize
int dp[][] = new int[n][MAX];
for(int i = 0; i < n; i++)
for(int j = 0; j < MAX; j++)
dp[i][j] = -1;
// Count the number of subsequences
int count = 0;
// Count for every subsequence
for (int i = 0; i < n; i++)
count += func(i + 1, a[i], dp, n, a);
return count;
}
// Driver Code
public static void main(String args[])
{
int a[] = { 3, 4, 8, 16 };
int n = a.length;
System.out.println(countSubsequences(a, n));
}
}
// This code is contributed by Arnab Kundu
Python3
# Python3 program to find the number
# of subsequences with gcd 1
MAX = 1000
def gcd(a, b):
if (a == 0):
return b
return gcd(b % a, a)
# Recursive function to calculate the
# number of subsequences with gcd 1
# starting with particular index
def func(ind, g, dp, n, a):
# Base case
if (ind == n):
if (g == 1):
return 1
else:
return 0
# If already visited
if (dp[ind][g] != -1):
return dp[ind][g]
# Either we take or we do not
ans = (func(ind + 1, g, dp, n, a) +
func(ind + 1, gcd(a[ind], g),
dp, n, a))
# Return the answer
dp[ind][g] = ans
return dp[ind][g]
# Function to return the number
# of subsequences
def countSubsequences(a, n):
# Hash table to memoize
dp = [[-1 for i in range(MAX)]
for i in range(n)]
# Count the number of subsequences
count = 0
# Count for every subsequence
for i in range(n):
count += func(i + 1, a[i], dp, n, a)
return count
# Driver Code
a = [3, 4, 8, 16 ]
n = len(a)
print(countSubsequences(a, n))
# This code is contributed by mohit kumar 29
C#
// C# program to find the number
// of subsequences with gcd 1
using System;
class GFG
{
static int gcd(int a, int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
// Recursive function to calculate the number
// of subsequences with gcd 1 starting with
// particular index
static int func(int ind, int g, int [][] dp,
int n, int [] a)
{
// Base case
if (ind == n)
{
if (g == 1)
return 1;
else
return 0;
}
// If already visited
if (dp[ind][g] != -1)
return dp[ind][g];
// Either we take or we do not
int ans = func(ind + 1, g, dp, n, a)
+ func(ind + 1, gcd(a[ind], g), dp, n, a);
// Return the answer
return dp[ind][g] = ans;
}
// Function to return the
// number of subsequences
static int countSubsequences(int [] a, int n)
{
// Hash table to memoize
int [][] dp = new int[n][];
for(int i = 0; i < n; i++)
for(int j = 0; j < 1000; j++)
dp[i][j] = -1;
// Count the number of subsequences
int count = 0;
// Count for every subsequence
for (int i = 0; i < n; i++)
count += func(i + 1, a[i], dp, n, a);
return count;
}
// Driver Code
public static void Main()
{
int [] a = { 3, 4, 8, 16 };
int n = 4;
int x = countSubsequences(a, n);
Console.Write(x);
}
}
// This code is contributed by
// mohit kumar 29
PHP
Javascript
C++
// C++ program for above approach
#include
using namespace std;
// This function calculates
// gcd of two number
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// This function will return total
// subsequences
int countSubsequences(int arr[], int n)
{
// Declare a dp 2d array
long long int dp[n][101] = {0};
// Iterate i from 0 to n - 1
for(int i = 0; i < n; i++)
{
dp[i][arr[i]] = 1;
// Iterate j from i - 1 to 0
for(int j = i - 1; j >= 0; j--)
{
if(arr[j] < arr[i])
{
// Iterate k from 0 to 100
for(int k = 0; k <= 100; k++)
{
// Find gcd of two number
int GCD = gcd(arr[i], k);
// dp[i][GCD] is summation of
// dp[i][GCD] and dp[j][k]
dp[i][GCD] = dp[i][GCD] +
dp[j][k];
}
}
}
}
// Add all elements of dp[i][1]
long long int sum = 0;
for(int i = 0; i < n; i++)
{
sum=(sum + dp[i][1]);
}
// Return sum
return sum;
}
// Driver code
int main()
{
int a[] = { 3, 4, 8, 16 };
int n = sizeof(a) / sizeof(a[0]);
// Function Call
cout << countSubsequences(a, n);
return 0;
}
Java
// Java program for the
// above approach
import java.util.*;
class GFG{
// This function calculates
// gcd of two number
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// This function will return total
// subsequences
static long countSubsequences(int arr[],
int n)
{
// Declare a dp 2d array
long dp[][] = new long[n][101];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < 101; j++)
{
dp[i][j] = 0;
}
}
// Iterate i from 0 to n - 1
for(int i = 0; i < n; i++)
{
dp[i][arr[i]] = 1;
// Iterate j from i - 1 to 0
for(int j = i - 1; j >= 0; j--)
{
if (arr[j] < arr[i])
{
// Iterate k from 0 to 100
for(int k = 0; k <= 100; k++)
{
// Find gcd of two number
int GCD = gcd(arr[i], k);
// dp[i][GCD] is summation of
// dp[i][GCD] and dp[j][k]
dp[i][GCD] = dp[i][GCD] +
dp[j][k];
}
}
}
}
// Add all elements of dp[i][1]
long sum = 0;
for(int i = 0; i < n; i++)
{
sum = (sum + dp[i][1]);
}
// Return sum
return sum;
}
// Driver code
public static void main(String args[])
{
int a[] = { 3, 4, 8, 16 };
int n = a.length;
// Function Call
System.out.println(countSubsequences(a, n));
}
}
// This code is contributed by bolliranadheer
Python3
# Python3 program for the
# above approach
# This function calculates
# gcd of two number
def gcd(a, b):
if (b == 0):
return a;
return gcd(b, a % b);
# This function will return total
# subsequences
def countSubsequences(arr, n):
# Declare a dp 2d array
dp = [[0 for i in range(101)] for j in range(n)]
# Iterate i from 0 to n - 1
for i in range(n):
dp[i][arr[i]] = 1;
# Iterate j from i - 1 to 0
for j in range(i - 1, -1, -1):
if (arr[j] < arr[i]):
# Iterate k from 0 to 100
for k in range(101):
# Find gcd of two number
GCD = gcd(arr[i], k);
# dp[i][GCD] is summation of
# dp[i][GCD] and dp[j][k]
dp[i][GCD] = dp[i][GCD] + dp[j][k];
# Add all elements of dp[i][1]
sum = 0;
for i in range(n):
sum = (sum + dp[i][1]);
# Return sum
return sum;
# Driver code
if __name__=='__main__':
a = [ 3, 4, 8, 16 ]
n = len(a)
# Function Call
print(countSubsequences(a,n))
# This code is contributed by Pratham76
C#
// C# program for the above approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
// This function calculates
// gcd of two number
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// This function will return total
// subsequences
static long countSubsequences(int []arr,
int n)
{
// Declare a dp 2d array
long [,]dp = new long[n, 101];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < 101; j++)
{
dp[i, j] = 0;
}
}
// Iterate i from 0 to n - 1
for(int i = 0; i < n; i++)
{
dp[i, arr[i]] = 1;
// Iterate j from i - 1 to 0
for(int j = i - 1; j >= 0; j--)
{
if (arr[j] < arr[i])
{
// Iterate k from 0 to 100
for(int k = 0; k <= 100; k++)
{
// Find gcd of two number
int GCD = gcd(arr[i], k);
// dp[i,GCD] is summation of
// dp[i,GCD] and dp[j,k]
dp[i, GCD] = dp[i, GCD] +
dp[j, k];
}
}
}
}
// Add all elements of dp[i,1]
long sum = 0;
for(int i = 0; i < n; i++)
{
sum = (sum + dp[i, 1]);
}
// Return sum
return sum;
}
// Driver code
public static void Main(string []args)
{
int []a = { 3, 4, 8, 16 };
int n = a.Length;
// Function Call
Console.WriteLine(countSubsequences(a, n));
}
}
// This code is contributed by rutvik_56
Javascript
输出
7
替代解决方案:计算 GCD 等于给定数量的集合的子集数量
无需记忆即可解决此问题的动态编程方法:
基本上,该方法将制作一个二维矩阵,其中 i 坐标将是给定数组元素的位置,j 坐标将是从 0 到 100 的数字,即。如果数组元素不够大,gcd 可以在 0 到 100 之间变化。我们将迭代给定的数组,二维矩阵将存储信息,直到第 i 个位置有多少子序列有 gcd 从 1 到 100 变化。稍后,我们将添加 dp[i][1] 以获得所有具有 gcd 的子序列作为1。
下面是上述方法的实现:
C++
// C++ program for above approach
#include
using namespace std;
// This function calculates
// gcd of two number
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// This function will return total
// subsequences
int countSubsequences(int arr[], int n)
{
// Declare a dp 2d array
long long int dp[n][101] = {0};
// Iterate i from 0 to n - 1
for(int i = 0; i < n; i++)
{
dp[i][arr[i]] = 1;
// Iterate j from i - 1 to 0
for(int j = i - 1; j >= 0; j--)
{
if(arr[j] < arr[i])
{
// Iterate k from 0 to 100
for(int k = 0; k <= 100; k++)
{
// Find gcd of two number
int GCD = gcd(arr[i], k);
// dp[i][GCD] is summation of
// dp[i][GCD] and dp[j][k]
dp[i][GCD] = dp[i][GCD] +
dp[j][k];
}
}
}
}
// Add all elements of dp[i][1]
long long int sum = 0;
for(int i = 0; i < n; i++)
{
sum=(sum + dp[i][1]);
}
// Return sum
return sum;
}
// Driver code
int main()
{
int a[] = { 3, 4, 8, 16 };
int n = sizeof(a) / sizeof(a[0]);
// Function Call
cout << countSubsequences(a, n);
return 0;
}
Java
// Java program for the
// above approach
import java.util.*;
class GFG{
// This function calculates
// gcd of two number
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// This function will return total
// subsequences
static long countSubsequences(int arr[],
int n)
{
// Declare a dp 2d array
long dp[][] = new long[n][101];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < 101; j++)
{
dp[i][j] = 0;
}
}
// Iterate i from 0 to n - 1
for(int i = 0; i < n; i++)
{
dp[i][arr[i]] = 1;
// Iterate j from i - 1 to 0
for(int j = i - 1; j >= 0; j--)
{
if (arr[j] < arr[i])
{
// Iterate k from 0 to 100
for(int k = 0; k <= 100; k++)
{
// Find gcd of two number
int GCD = gcd(arr[i], k);
// dp[i][GCD] is summation of
// dp[i][GCD] and dp[j][k]
dp[i][GCD] = dp[i][GCD] +
dp[j][k];
}
}
}
}
// Add all elements of dp[i][1]
long sum = 0;
for(int i = 0; i < n; i++)
{
sum = (sum + dp[i][1]);
}
// Return sum
return sum;
}
// Driver code
public static void main(String args[])
{
int a[] = { 3, 4, 8, 16 };
int n = a.length;
// Function Call
System.out.println(countSubsequences(a, n));
}
}
// This code is contributed by bolliranadheer
Python3
# Python3 program for the
# above approach
# This function calculates
# gcd of two number
def gcd(a, b):
if (b == 0):
return a;
return gcd(b, a % b);
# This function will return total
# subsequences
def countSubsequences(arr, n):
# Declare a dp 2d array
dp = [[0 for i in range(101)] for j in range(n)]
# Iterate i from 0 to n - 1
for i in range(n):
dp[i][arr[i]] = 1;
# Iterate j from i - 1 to 0
for j in range(i - 1, -1, -1):
if (arr[j] < arr[i]):
# Iterate k from 0 to 100
for k in range(101):
# Find gcd of two number
GCD = gcd(arr[i], k);
# dp[i][GCD] is summation of
# dp[i][GCD] and dp[j][k]
dp[i][GCD] = dp[i][GCD] + dp[j][k];
# Add all elements of dp[i][1]
sum = 0;
for i in range(n):
sum = (sum + dp[i][1]);
# Return sum
return sum;
# Driver code
if __name__=='__main__':
a = [ 3, 4, 8, 16 ]
n = len(a)
# Function Call
print(countSubsequences(a,n))
# This code is contributed by Pratham76
C#
// C# program for the above approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
// This function calculates
// gcd of two number
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// This function will return total
// subsequences
static long countSubsequences(int []arr,
int n)
{
// Declare a dp 2d array
long [,]dp = new long[n, 101];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < 101; j++)
{
dp[i, j] = 0;
}
}
// Iterate i from 0 to n - 1
for(int i = 0; i < n; i++)
{
dp[i, arr[i]] = 1;
// Iterate j from i - 1 to 0
for(int j = i - 1; j >= 0; j--)
{
if (arr[j] < arr[i])
{
// Iterate k from 0 to 100
for(int k = 0; k <= 100; k++)
{
// Find gcd of two number
int GCD = gcd(arr[i], k);
// dp[i,GCD] is summation of
// dp[i,GCD] and dp[j,k]
dp[i, GCD] = dp[i, GCD] +
dp[j, k];
}
}
}
}
// Add all elements of dp[i,1]
long sum = 0;
for(int i = 0; i < n; i++)
{
sum = (sum + dp[i, 1]);
}
// Return sum
return sum;
}
// Driver code
public static void Main(string []args)
{
int []a = { 3, 4, 8, 16 };
int n = a.Length;
// Function Call
Console.WriteLine(countSubsequences(a, n));
}
}
// This code is contributed by rutvik_56
Javascript
输出
7