计算 GCD 等于 X 的子序列
给定一个由N个整数和一个正整数X组成的数组arr[] ,任务是用 GCD 精确计数X的子序列。
例子:
Input: arr[] = {6, 4, 30} X = 2
Output: 3
Explanation: Subsequences with GCD(=2) are { {6, 4, 30}, {4, 30}, {6, 4} }. Hence, 3 is the answer.
Input: arr[] = {6, 6, 6} X = 3
Output: 0
方法:给定的问题可以在动态规划的帮助下解决。请按照以下步骤解决给定的问题。
- 定义一个二维 dp 表dp[i][j] ,它将表示有效子序列的数量,直到索引i与 GCD(= j )。
- 对于每次迭代,我们有 2 个选择:
- 取当前元素: dp 表可以更新为dp[i + 1][gcd(j, arr[i])] += dp[i][j] 。
- 跳过当前元素: dp 表可以更新为dp[i+1][j] += dp[i][j] 。
- 基本情况是dp[0][0] = 1 。
- 由于两个数的 gcd 永远不会大于这两个数,所以j的值将达到数组中的最大元素。因此,它可以迭代求解,最终答案将是dp[N][X] 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the total subsequences
// having GCD = X
int totalValidSubsequences(
vector arr, int X, int N)
{
// Find the maximum element of
// the array
int mx = *max_element(
arr.begin(), arr.end());
// Check if X is greater than mx
if (X > mx) {
return 0;
}
// Make a 2-d dp table of
// size [n+1, mx + 1]
vector > dp(
N + 1, vector(mx + 1, 0));
// Base Case
dp[0][0] = 1;
for (int i = 0; i < N; i++) {
// Iterate through all possible
// indexes
for (int j = 0; j <= mx; j++) {
// Iterate through all
// possible values
// Case 1. Skip the element
dp[i + 1][j] += dp[i][j];
// Case 2. Skip the current element
dp[i + 1][__gcd(j, arr[i])] += dp[i][j];
}
}
// Return the answer dp[N][X]
return dp[N][X];
}
// Driver Code
int main()
{
vector arr = { 6, 4, 30 };
int X = 2;
int N = arr.size();
cout << totalValidSubsequences(arr, X, N);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.util.Arrays;
import java.util.Collections;
class GFG {
// Function to find maximum in arr[]
static int max(int[] arr)
{
// Initialize maximum element
int max = arr[0];
// Traverse array elements from second and
// compare every element with current max
for (int i = 1; i < arr.length; i++)
if (arr[i] > max)
max = arr[i];
return max;
}
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// Function to find the total subsequences
// having GCD = X
static int totalValidSubsequences(int[] arr,
int X, int N)
{
// Find the maximum element of
// the array
int mx = max(arr);
// Check if X is greater than mx
if (X > mx) {
return 0;
}
// Make a 2-d dp table of
// size [n+1, mx + 1]
int dp[][] = new int[N + 1][mx + 1];
// Base Case
dp[0][0] = 1;
for (int i = 0; i < N; i++) {
// Iterate through all possible
// indexes
for (int j = 0; j <= mx; j++) {
// Iterate through all
// possible values
// Case 1. Skip the element
dp[i + 1][j] += dp[i][j];
// Case 2. Skip the current element
dp[i + 1][gcd(j, arr[i])] += dp[i][j];
}
}
// Return the answer dp[N][X]
return dp[N][X];
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 6, 4, 30 };
int X = 2;
int N = arr.length;
System.out.println(totalValidSubsequences(arr, X, N));
}
}
// This code is contributed by Dharanendra L V.
Python3
# Python 3 program for the above approach
from math import gcd
# Function to find the total subsequences
# having GCD = X
def totalValidSubsequences(arr, X, N):
# Find the maximum element of
# the array
mx = max(arr)
# Check if X is greater than mx
if (X > mx):
return 0
# Make a 2-d dp table of
# size [n+1, mx + 1]
dp = [[0 for i in range(mx+1)] for j in range(N + 1)]
# Base Case
dp[0][0] = 1
for i in range(N):
# Iterate through all possible
# indexes
for j in range(mx+1):
# Iterate through all
# possible values
# Case 1. Skip the element
dp[i + 1][j] += dp[i][j]
# Case 2. Skip the current element
dp[i + 1][gcd(j, arr[i])] += dp[i][j]
# Return the answer dp[N][X]
return dp[N][X]
# Driver Code
if __name__ == '__main__':
arr = [6, 4, 30]
X = 2
N = len(arr)
print(totalValidSubsequences(arr, X, N))
# This code is contributed by SURENDRA_GANGWAR.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Function to find maximum in arr[]
static int max(int []arr)
{
// Initialize maximum element
int max = arr[0];
// Traverse array elements from second and
// compare every element with current max
for (int i = 1; i < arr.Length; i++)
if (arr[i] > max)
max = arr[i];
return max;
}
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
// Function to find the total subsequences
// having GCD = X
static int totalValidSubsequences(int[] arr,
int X, int N)
{
// Find the maximum element of
// the array
int mx = max(arr);
// Check if X is greater than mx
if (X > mx) {
return 0;
}
// Make a 2-d dp table of
// size [n+1, mx + 1]
int[,] dp = new int[N + 1, mx + 1];
// Base Case
dp[0, 0] = 1;
for (int i = 0; i < N; i++) {
// Iterate through all possible
// indexes
for (int j = 0; j <= mx; j++) {
// Iterate through all
// possible values
// Case 1. Skip the element
dp[i + 1, j] += dp[i, j];
// Case 2. Skip the current element
dp[i + 1, gcd(j, arr[i])] += dp[i, j];
}
}
// Return the answer dp[N][X]
return dp[N, X];
}
// Driver Code
public static void Main()
{
int[] arr = { 6, 4, 30 };
int X = 2;
int N = arr.Length;
Console.Write(totalValidSubsequences(arr, X, N));
}
}
// This code is contributed by _saurabh_jaiswal
Javascript
输出:
3
时间复杂度: O(N*M),其中M是数组的最大元素。
辅助空间: O(N*M)