给定一个大小为N的数组a 。任务是找到一个长度为K的子序列X ,使得gcd(X[0], X[1]) + (X[2], X[3]) + …是最大值。
注: K是偶数。
例子:
Input: a[] = {4, 5, 3, 7, 8, 10, 9, 8}, k = 4
Output: 9
The subsequence {4, 7, 8, 8} gives the maximum value = 9.
Other subsequences like { 5, 3, 8, 8} also gives 9.
Input: a[] = {5, 8, 16, 20}, K = 2
Output:
The subsequence {8, 16} gives the maximum value.
朴素的方法:朴素的方法是使用递归生成所有长度为 K 的子序列并找到可能的最大值。
高效的方法: 一种有效的方法是使用动态规划来解决上述问题。如果将第 i 个索引元素作为第j 个元素,则让dp[i][j]表示对 gcd sum 的值。递归生成所有可能的子序列。如果所取元素的cnt为奇数,则将gcd (a[prev], a[current]) 添加到总和中,因为该数字将是该对中的第二个,并为下一个元素重复出现。如果cnt是even ,则只需重复设置a[i]作为前一个元素。记忆已被用于避免重新计算相同的重复。所有生成的总和的最大值将是答案。
下面是上述方法的实现:
C++
// C++ program to find the sum of
// the addition of all possible subsets
#include
using namespace std;
const int MAX = 100;
// Recursive function to find the maximum value of
// the given recurrence
int recur(int ind, int cnt, int last, int a[],
int n, int k, int dp[][MAX])
{
// If we get K elements
if (cnt == k)
return 0;
// If we have reached the end
// and K elements are not there
if (ind == n)
return -1e9;
// If the state has been visited
if (dp[ind][cnt] != -1)
return dp[ind][cnt];
int ans = 0;
// Iterate for every element as the
// next possible element
// and take the element which gives
// the maximum answer
for (int i = ind; i < n; i++)
{
// If this element is the first element
// in the individual pair in the subsequence
// then simply recurrence with the last
// element as i-th index
if (cnt % 2 == 0)
ans=max(ans,recur(i + 1, cnt + 1, i, a, n, k, dp));
// If this element is the second element in
// the individual pair, the find gcd with
// the previous element and add to the answer
// and recur for the next element
else
ans = max(ans, __gcd(a[last], a[i]) +
recur(i + 1, cnt + 1, 0, a, n, k, dp));
}
return dp[ind][cnt] = ans;
}
// Driver Code
int main()
{
int a[] = { 4, 5, 3, 7, 8, 10, 9, 8 };
int n = sizeof(a) / sizeof(a[0]);
int k = 4;
int dp[n][MAX];
memset(dp, -1, sizeof dp);
cout << recur(0, 0, 0, a, n, k, dp);
}
Java
// Java program to find the sum of
// the addition of all possible subsets
import java.util.*;
class GFG
{
static int MAX = 100;
// Recursive function to find the maximum value of
// the given recurrence
static int recur(int ind, int cnt, int last, int a[],
int n, int k, int dp[][])
{
// If we get K elements
if (cnt == k)
return 0;
// If we have reached the end
// and K elements are not there
if (ind == n)
return (int) -1e9;
// If the state has been visited
if (dp[ind][cnt] != -1)
return dp[ind][cnt];
int ans = 0;
// Iterate for every element as the
// next possible element
// and take the element which gives
// the maximum answer
for (int i = ind; i < n; i++)
{
// If this element is the first element
// in the individual pair in the subsequence
// then simply recurrence with the last
// element as i-th index
if (cnt % 2 == 0)
ans = Math.max(ans,recur(i + 1, cnt + 1, i, a, n, k, dp));
// If this element is the second element in
// the individual pair, the find gcd with
// the previous element and add to the answer
// and recur for the next element
else
ans = Math.max(ans, __gcd(a[last], a[i]) +
recur(i + 1, cnt + 1, 0, a, n, k, dp));
}
return dp[ind][cnt] = ans;
}
static int __gcd(int a, int b)
{
if (b == 0)
return a;
return __gcd(b, a % b);
}
// Driver Code
public static void main(String[] args)
{
int a[] = { 4, 5, 3, 7, 8, 10, 9, 8 };
int n = a.length;
int k = 4;
int [][]dp = new int[n][MAX];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < MAX; j++)
{
dp[i][j] = -1;
}
}
System.out.println(recur(0, 0, 0, a, n, k, dp));
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 program to find the sum of
# the addition of all possible subsets
from math import gcd as __gcd
MAX = 100
# Recursive function to find the
# maximum value of the given recurrence
def recur(ind, cnt, last, a, n, k, dp):
# If we get K elements
if (cnt == k):
return 0
# If we have reached the end
# and K elements are not there
if (ind == n):
return -10**9
# If the state has been visited
if (dp[ind][cnt] != -1):
return dp[ind][cnt]
ans = 0
# Iterate for every element as the
# next possible element
# and take the element which gives
# the maximum answer
for i in range(ind, n):
# If this element is the first element
# in the individual pair in the subsequence
# then simply recurrence with the last
# element as i-th index
if (cnt % 2 == 0):
ans = max(ans, recur(i + 1, cnt + 1,
i, a, n, k, dp))
# If this element is the second element in
# the individual pair, the find gcd with
# the previous element and add to the answer
# and recur for the next element
else:
ans = max(ans, __gcd(a[last], a[i]) +
recur(i + 1, cnt + 1, 0, a, n, k, dp))
dp[ind][cnt] = ans
return ans
# Driver Code
a = [4, 5, 3, 7, 8, 10, 9, 8 ]
n = len(a)
k = 4;
dp = [[-1 for i in range(MAX)]
for i in range(n)]
print(recur(0, 0, 0, a, n, k, dp))
# This code is contributed by Mohit Kumar
C#
// C# program to find the sum of
// the addition of all possible subsets
using System;
class GFG
{
static int MAX = 100;
// Recursive function to find the maximum value of
// the given recurrence
static int recur(int ind, int cnt, int last, int []a,
int n, int k, int [,]dp)
{
// If we get K elements
if (cnt == k)
return 0;
// If we have reached the end
// and K elements are not there
if (ind == n)
return (int) -1e9;
// If the state has been visited
if (dp[ind,cnt] != -1)
return dp[ind,cnt];
int ans = 0;
// Iterate for every element as the
// next possible element
// and take the element which gives
// the maximum answer
for (int i = ind; i < n; i++)
{
// If this element is the first element
// in the individual pair in the subsequence
// then simply recurrence with the last
// element as i-th index
if (cnt % 2 == 0)
ans = Math.Max(ans,recur(i + 1, cnt + 1, i, a, n, k, dp));
// If this element is the second element in
// the individual pair, the find gcd with
// the previous element and add to the answer
// and recur for the next element
else
ans = Math.Max(ans, __gcd(a[last], a[i]) +
recur(i + 1, cnt + 1, 0, a, n, k, dp));
}
return dp[ind,cnt] = ans;
}
static int __gcd(int a, int b)
{
if (b == 0)
return a;
return __gcd(b, a % b);
}
// Driver Code
public static void Main(String[] args)
{
int []a = { 4, 5, 3, 7, 8, 10, 9, 8 };
int n = a.Length;
int k = 4;
int [,]dp = new int[n,MAX];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < MAX; j++)
{
dp[i,j] = -1;
}
}
Console.WriteLine(recur(0, 0, 0, a, n, k, dp));
}
}
// This code is contributed by Princi Singh
Javascript
9
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。