📌  相关文章
📜  通过串联长度为素数的不相交子数组获得的最大子序列总和

📅  最后修改于: 2021-04-23 06:08:05             🧑  作者: Mango

给定大小为N的数组arr [] 任务是找到通过合并长度为质数的不相交子数组形成的子序列的最大和。

例子:

天真的方法:最简单的方法是使用递归来计算子序列的最大和的值。在每个步骤中,对小于N的每个素数调用多个递归调用。递归关系由下式给出:

上面的重复关系仅适用于一个素数。因此,通过选择不同素数长度的不同子阵列可以形成不止一个可能的子序列。下面是形成的递归关系:

时间复杂度: O(K N ),其中K是小于N数的数目。大约K =(N / LogN)
辅助空间:O (1)

使用自下而上方法的动态编程也可以使用辅助数组dp []减少上述递归调用,并以自下而上的方法计算每个状态的值。步骤如下:

  • 创建一个辅助数组prime []来存储所有小于或等于N的素数。
  • 维护Eratosthenes筛并遍历它以填充数组prime []的值。
  • 创建大小为N的辅助数组dp []
  • 将状态01初始化为dp [0] = 0dp [1] = 0
  • [2,N]范围内遍历数组dp [ ]并将每个状态更新为:
  • 初始化pref []数组以存储前缀和,以有效地计算sum(l,…,r)
  • 在上述步骤之后,打印dp [N]的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
#define MAX 100005
 
// Function to return all prime numbers
// smaller than N
vector SieveOfEratosthenes()
{
    // Create a boolean array "prime[0..n]"
    bool seive[MAX];
 
    // Initialize all its entries as true
    memset(seive, true, sizeof(seive));
 
    for (int p = 2; p * p < MAX; p++) {
 
        // If prime[p] is not changed,
        // then it is a prime
        if (seive[p] == true) {
 
            // Update all multiples of
            // p greater than or equal
            // to the square of it
            for (int i = p * p;
                 i < MAX; i += p) {
                seive[i] = false;
            }
        }
    }
 
    // Stores all prime numbers
    // smaller than MAX
    vector v;
 
    // Store all prime numbers
    for (int p = 2; p < MAX; p++) {
 
        // If p is prime
        if (seive[p]) {
            v.push_back(p);
        }
    }
 
    return v;
}
 
// Function to build the auxiliary DP
// array from the start
void build(int dp[], int arr[], int N)
{
    // Base Case
    dp[0] = 0;
    dp[1] = 0;
 
    // Stores all prime numbers < N
    vector prime
        = SieveOfEratosthenes();
 
    // Stores prefix sum
    int pref[N + 1];
    pref[0] = 0;
 
    // Update prefix sum
    for (int i = 1; i <= N; i++) {
        pref[i] = pref[i - 1]
                  + arr[i - 1];
    }
 
    // Iterate over range
    for (int i = 2; i <= N; i++) {
 
        // Update each state i.e.. when
        // current element is excluded
        dp[i] = dp[i - 1];
        for (int j = 0;
             j <= prime.size(); j++) {
 
            // Find start & end index
            // of subarrays when prime[i]
            // is taken
            int r = i - 1;
            int l = r - prime[j] + 1;
 
            // Check if starting point
            // lies in the array
            if (l < 0)
                break;
            int temp = 0;
 
            // Include the elements
            // al al+1 ... ar
            temp = pref[r + 1] - pref[l];
 
            // Check if element lies before
            // start of selected subarray
            if (l - 2 >= 0)
                temp += dp[l - 2 + 1];
 
            // Update value of dp[i]
            dp[i] = max(dp[i], temp);
        }
    }
}
 
// Function to find the maximum sum
// subsequence with prime length
void maxSumSubseq(int arr[], int N)
{
    // Auxiliary DP array
    int dp[N + 1];
 
    // Build DP array
    build(dp, arr, N);
 
    // Print the result
    cout << dp[N];
}
 
// Driver Code
int main()
{
    // Given arr[]
    int arr[] = { 10, 10, 7, 10, 10, 10 };
 
    // Size of array
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    maxSumSubseq(arr, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
     
static int MAX = 100005;
 
// Function to return all prime numbers
// smaller than N
static Vector SieveOfEratosthenes()
{
     
    // Create a boolean array "prime[0..n]"
    boolean []seive = new boolean[MAX];
 
    // Initialize all its entries as true
    Arrays.fill(seive, true);
 
    for(int p = 2; p * p < MAX; p++)
    {
         
        // If prime[p] is not changed,
        // then it is a prime
        if (seive[p] == true)
        {
             
            // Update all multiples of
            // p greater than or equal
            // to the square of it
            for(int i = p * p; i < MAX; i += p)
            {
                seive[i] = false;
            }
        }
    }
 
    // Stores all prime numbers
    // smaller than MAX
    Vector v = new Vector();
 
    // Store all prime numbers
    for(int p = 2; p < MAX; p++)
    {
         
        // If p is prime
        if (seive[p])
        {
            v.add(p);
        }
    }
    return v;
}
 
// Function to build the auxiliary DP
// array from the start
static void build(int dp[], int arr[], int N)
{
     
    // Base Case
    dp[0] = 0;
    dp[1] = 0;
 
    // Stores all prime numbers < N
    Vector prime = SieveOfEratosthenes();
 
    // Stores prefix sum
    int []pref = new int[N + 1];
    pref[0] = 0;
 
    // Update prefix sum
    for(int i = 1; i <= N; i++)
    {
        pref[i] = pref[i - 1] + arr[i - 1];
    }
 
    // Iterate over range
    for(int i = 2; i <= N; i++)
    {
         
        // Update each state i.e.. when
        // current element is excluded
        dp[i] = dp[i - 1];
        for(int j = 0; j <= prime.size(); j++)
        {
             
            // Find start & end index
            // of subarrays when prime[i]
            // is taken
            int r = i - 1;
            int l = r - prime.get(j) + 1;
 
            // Check if starting point
            // lies in the array
            if (l < 0)
                break;
                 
            int temp = 0;
 
            // Include the elements
            // al al+1 ... ar
            temp = pref[r + 1] - pref[l];
 
            // Check if element lies before
            // start of selected subarray
            if (l - 2 >= 0)
                temp += dp[l - 2 + 1];
 
            // Update value of dp[i]
            dp[i] = Math.max(dp[i], temp);
        }
    }
}
 
// Function to find the maximum sum
// subsequence with prime length
static void maxSumSubseq(int arr[], int N)
{
     
    // Auxiliary DP array
    int []dp = new int[N + 1];
 
    // Build DP array
    build(dp, arr, N);
 
    // Print the result
    System.out.print(dp[N]);
}
 
// Driver Code
public static void main(String args[])
{
     
    // Given arr[]
    int arr[] = { 10, 10, 7, 10, 10, 10 };
 
    // Size of array
    int N = arr.length;
 
    // Function Call
    maxSumSubseq(arr, N);
}
}
 
// This code is contributed by ipg2016107


Python3
# Python3 program for the above approach
MAX = 100005
 
# Function to return all prime numbers
# smaller than N
def SieveOfEratosthenes():
     
    # Create a boolean array "prime[0..n]"
    seive = [True for i in range(MAX)]
 
    # Initialize all its entries as true
    # memset(seive, true, sizeof(seive))
    for p in range(2, MAX):
        if p * p > MAX:
            break
         
        # If prime[p] is not changed,
        # then it is a prime
        if (seive[p] == True):
 
            # Update all multiples of
            # p greater than or equal
            # to the square of it
            for i in range(p * p, MAX, p):
                seive[i] = False
 
    # Stores all prime numbers
    # smaller than MAX
    v = []
 
    # Store all prime numbers
    for p in range(2, MAX):
         
        # If p is prime
        if (seive[p]):
            v.append(p)
 
    return v
 
# Function to build the auxiliary DP
# array from the start
def build(dp, arr, N):
     
    # Base Case
    dp[0] = 0
    dp[1] = 0
 
    # Stores all prime numbers < N
    prime = SieveOfEratosthenes()
 
    # Stores prefix sum
    pref = [0 for i in range(N + 1)]
    pref[0] = 0
 
    # Update prefix sum
    for i in range(1, N + 1):
        pref[i] = pref[i - 1] + arr[i - 1]
 
    # Iterate over range
    for i in range(2, N + 1):
 
        # Update each state i.e.. when
        # current element is excluded
        dp[i] = dp[i - 1]
         
        for j in range(len(prime) + 1):
 
            # Find start & end index
            # of subarrays when prime[i]
            # is taken
            r = i - 1
            l = r - prime[j] + 1
 
            # Check if starting point
            # lies in the array
            if (l < 0):
                break
             
            temp = 0
 
            # Include the elements
            # al al+1 ... ar
            temp = pref[r + 1] - pref[l]
 
            # Check if element lies before
            # start of selected subarray
            if (l - 2 >= 0):
                temp += dp[l - 2 + 1]
 
            # Update value of dp[i]
            dp[i] = max(dp[i], temp)
 
# Function to find the maximum sum
# subsequence with prime length
def maxSumSubseq(arr, N):
     
    # Auxiliary DP array
    dp = [0 for i in range(N + 1)]
 
    # Build DP array
    build(dp, arr, N)
 
    # Print the result
    print(dp[N])
 
# Driver Code
if __name__ == '__main__':
     
    # Given arr[]
    arr = [ 10, 10, 7, 10, 10, 10 ]
 
    # Size of array
    N = len(arr)
 
    # Function Call
    maxSumSubseq(arr, N)
 
# This code is contributed by mohit kumar 29


C#
// C# program for the
// above approach
using System;
using System.Collections.Generic;
class GFG{
     
static int MAX = 100005;
 
// Function to return all
// prime numbers smaller than N
static List SieveOfEratosthenes()
{   
  // Create a bool array
  // "prime[0..n]"
  bool []seive = new bool[MAX];
 
  // Initialize all its entries
  // as true
  for(int i = 0; i < MAX; i++)
    seive[i] = true;
 
  for(int p = 2; p * p < MAX; p++)
  {
    // If prime[p] is not changed,
    // then it is a prime
    if (seive[p] == true)
    {
      // Update all multiples of
      // p greater than or equal
      // to the square of it
      for(int i = p * p;
              i < MAX; i += p)
      {
        seive[i] = false;
      }
    }
  }
 
  // Stores all prime numbers
  // smaller than MAX
  List v = new List();
 
  // Store all prime numbers
  for(int p = 2; p < MAX; p++)
  {
    // If p is prime
    if (seive[p])
    {
      v.Add(p);
    }
  }
  return v;
}
 
// Function to build the auxiliary
// DP array from the start
static void build(int []dp,
                  int []arr, int N)
{   
  // Base Case
  dp[0] = 0;
  dp[1] = 0;
 
  // Stores all prime
  // numbers < N
  List prime =
            SieveOfEratosthenes();
 
  // Stores prefix sum
  int []pref = new int[N + 1];
  pref[0] = 0;
 
  // Update prefix sum
  for(int i = 1; i <= N; i++)
  {
    pref[i] = pref[i - 1] +
              arr[i - 1];
  }
 
  // Iterate over range
  for(int i = 2; i <= N; i++)
  {
    // Update each state i.e..
    // when current element
    // is excluded
    dp[i] = dp[i - 1];
    for(int j = 0;
            j <= prime.Count; j++)
    {
      // Find start & end index
      // of subarrays when prime[i]
      // is taken
      int r = i - 1;
      int l = r - prime[j] + 1;
 
      // Check if starting point
      // lies in the array
      if (l < 0)
        break;
 
      int temp = 0;
 
      // Include the elements
      // al al+1 ... ar
      temp = pref[r + 1] - pref[l];
 
      // Check if element lies
      // before start of selected
      // subarray
      if (l - 2 >= 0)
        temp += dp[l - 2 + 1];
 
      // Update value of dp[i]
      dp[i] = Math.Max(dp[i],
                       temp);
    }
  }
}
 
// Function to find the maximum
// sum subsequence with prime
// length
static void maxSumSubseq(int []arr,
                         int N)
{
  // Auxiliary DP array
  int []dp = new int[N + 1];
 
  // Build DP array
  build(dp, arr, N);
 
  // Print the result
  Console.Write(dp[N]);
}
 
// Driver Code
public static void Main(String []args)
{
  // Given []arr
  int []arr = {10, 10, 7,
               10, 10, 10};
 
  // Size of array
  int N = arr.Length;
 
  // Function Call
  maxSumSubseq(arr, N);
}
}
 
// This code is contributed by shikhasingrajput


输出
50

时间复杂度: O(N * K)
辅助空间: O(N)