📌  相关文章
📜  长度为K的子序列X,使得gcd(X [0],X [1])+(X [2],X [3])+…最大化

📅  最后修改于: 2021-04-24 04:10:28             🧑  作者: Mango

给定大小为N的数组a 。任务是找到长度为K的子序列X ,以使gcd(X [0],X [1])+(X [2],X [3])+…最大

注意K是偶数。

例子:

天真的方法:天真的方法是使用递归生成长度为K的所有子序列,并找到可能的最大值。

高效的方法:一种有效的方法是使用动态编程来解决上述问题。令dp [i] [j]表示如果将第i个索引元素作为第j个元素,则对gcd sum的值。递归生成所有可能的子序列。如果所取元素的cnt奇数,则将gcd(a [prev],a [current])添加到总和中,因为此数字将是该对中的第二个元素,并在下一个元素中重复出现。如果cnteven ,则只需简单地将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


输出:
9