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

📅  最后修改于: 2021-09-05 11:52:46             🧑  作者: 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 以有效计算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


Javascript


输出
50

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

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live