📌  相关文章
📜  计算将数组拆分为子数组的方法,使得第 i 个子数组的总和可以被 i 整除

📅  最后修改于: 2022-05-13 01:56:04.547000             🧑  作者: Mango

计算将数组拆分为子数组的方法,使得第 i 个子数组的总和可以被 i 整除

给定一个由N个整数组成的数组arr[] ,任务是找到将数组拆分为非空子数组的方法数,使得第i个子数组的总和可以被i整除。

例子:

方法:给定的问题可以通过使用动态规划来解决,因为它具有重叠的子问题和最优的子结构。子问题可以使用记忆存储在dp[][] 表中,其中dp[i][j]将分区数存储到arr[]第 i 个索引到j个非空子数组中。这个想法可以使用 Prefix Sum 数组pre[]来实现,该数组存储所有元素的总和,直到每个i th索引,并且dp[i][j]可以计算为dp[k][j – 1]的总和k < i的所有值使得(pre[i] – pre[k])j的倍数。请按照以下步骤解决给定的问题:

  • 初始化一个变量,比如count ,它将给定数组的可能拆分次数存储到子数组中。
  • 找到数组的前缀和并将其存储在另一个数组中,比如prefix[]
  • 初始化一个二维数组,例如dp[][] ,它存储所有重叠状态dp[i][j]
  • 使用变量i迭代范围[0, N]并使用变量j嵌套迭代范围[N, 0]并执行以下步骤:
    1. dp[j + 1][pre[i + 1] % (j + 1)]的值增加dp[j][pre[i + 1] % j]的值,因为这表示分区的计数,直到索引ij可被(j + 1)整除的连续子序列中。
    2. 如果i的值为(N – 1) ,则将count的值更新为dp[j][pre[i + 1] % j]
  • 完成上述步骤后,打印count的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to count ways to split
// an array into subarrays such that
// sum of the i-th subarray is
// divisible by i
int countOfWays(int arr[], int N)
{
 
    // Stores the prefix sum of array
    int pre[N + 1] = { 0 };
    for (int i = 0; i < N; i++) {
 
        // Find the prefix sum
        pre[i + 1] = pre[i] + arr[i];
    }
 
    // Initialize dp[][] array
    int dp[N + 1][N + 1];
    memset(dp, 0, sizeof(dp));
    dp[1][0]++;
 
    // Stores the count of splitting
    int ans = 0;
 
    // Iterate over the range [0, N]
    for (int i = 0; i < N; i++) {
        for (int j = N; j >= 1; j--) {
 
            // Update the dp table
            dp[j + 1][pre[i + 1] % (j + 1)]
                += dp[j][pre[i + 1] % j];
 
            // If the last index is
            // reached, then add it
            // to the variable ans
            if (i == N - 1) {
                ans += dp[j][pre[i + 1] % j];
            }
        }
    }
 
    // Return the possible count of
    // splitting of array into subarrays
    return ans;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 2, 3, 4 };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << countOfWays(arr, N);
 
    return 0;
}


Java
// Java program for the above approach
 
public class GFG {
     
 
// Function to count ways to split
// an array into subarrays such that
// sum of the i-th subarray is
// divisible by i
static int countOfWays(int arr[], int N)
{
 
    // Stores the prefix sum of array
    int pre[] = new int[N + 1];
     
    for (int i = 0; i < N; i++) {
 
        // Find the prefix sum
        pre[i + 1] = pre[i] + arr[i];
    }
 
    // Initialize dp[][] array
    int dp[][] = new int [N + 2][N + 2];
 
    dp[1][0]++;
 
    // Stores the count of splitting
    int ans = 0;
 
    // Iterate over the range [0, N]
    for (int i = 0; i < N; i++) {
        for (int j = N; j >= 1; j--) {
 
            // Update the dp table
            dp[j + 1][pre[i + 1] % (j + 1)]
                += dp[j][pre[i + 1] % j];
 
            // If the last index is
            // reached, then add it
            // to the variable ans
            if (i == N - 1) {
                ans += dp[j][pre[i + 1] % j];
            }
        }
    }
 
    // Return the possible count of
    // splitting of array into subarrays
    return ans;
}
 
    // Driver Code
    public static void main (String[] args) {
         
            int arr[] = { 1, 2, 3, 4 };
            int N = arr.length;
         
            System.out.println(countOfWays(arr, N));
    }
}
 
// This code is contributed by AnkThon


Python3
# Python3 program for the above approach
 
import numpy as np
 
# Function to count ways to split
# an array into subarrays such that
# sum of the i-th subarray is
# divisible by i
def countOfWays(arr, N) :
 
    # Stores the prefix sum of array
    pre = [ 0 ] * (N + 1);
     
    for i in range(N) :
 
        # Find the prefix sum
        pre[i + 1] = pre[i] + arr[i];
 
    # Initialize dp[][] array
    dp = np.zeros((N + 2,N + 2));
    dp[1][0] += 1;
 
    # Stores the count of splitting
    ans = 0;
 
    # Iterate over the range [0, N]
    for i in range(N) :
        for j in range(N, 0, -1) :
 
            # Update the dp table
            dp[j + 1][pre[i + 1] % (j + 1)] += dp[j][pre[i + 1] % j];
 
            # If the last index is
            # reached, then add it
            # to the variable ans
            if (i == N - 1) :
                ans += dp[j][pre[i + 1] % j];
            
    # Return the possible count of
    # splitting of array into subarrays
    return ans;
 
 
# Driver Code
if __name__ ==  "__main__" :
 
    arr = [ 1, 2, 3, 4 ];
    N = len(arr);
 
    print(countOfWays(arr, N));
     
    # This code is contributed by AnkThon


C#
// C# program for the above approach
using System;
 
public class GFG
{
   
// Function to count ways to split
// an array into subarrays such that
// sum of the i-th subarray is
// divisible by i
static int countOfWays(int[] arr, int N)
{
 
    // Stores the prefix sum of array
    int[] pre = new int[N + 1];
     
    for (int i = 0; i < N; i++) {
 
        // Find the prefix sum
        pre[i + 1] = pre[i] + arr[i];
    }
 
    // Initialize dp[][] array
    int[,] dp = new int [N + 2, N + 2];
 
    dp[1, 0]++;
 
    // Stores the count of splitting
    int ans = 0;
 
    // Iterate over the range [0, N]
    for (int i = 0; i < N; i++) {
        for (int j = N; j >= 1; j--) {
 
            // Update the dp table
            dp[j + 1, pre[i + 1] % (j + 1)]
                += dp[j, pre[i + 1] % j];
 
            // If the last index is
            // reached, then add it
            // to the variable ans
            if (i == N - 1) {
                ans += dp[j, pre[i + 1] % j];
            }
        }
    }
 
    // Return the possible count of
    // splitting of array into subarrays
    return ans;
}
 
  // Driver Code
  public static void Main(String []args) {
     
    int[] arr = { 1, 2, 3, 4 };
    int N = arr.Length;
         
    Console.WriteLine(countOfWays(arr, N));
  }
 
}
 
// This code is contributed by sanjoy_62.


Javascript


输出
3

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