📜  用 GCD 1 计算子序列的数量

📅  最后修改于: 2022-05-13 01:57:51.072000             🧑  作者: Mango

用 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