📜  总和可被m整除的子集数

📅  最后修改于: 2021-04-24 22:23:14             🧑  作者: Mango

给定一个整数数组,请找到多个子序列,使得该子序列的和可被m整除。假设数组元素之和很小。
例子:

Input : arr[] = {1, 2, 3};
        m = 3;
Output : 3
Subsequence of given set are
{1}, {2}, {3}, {1, 2}, {2, 3}, {1, 3} and {1, 2, 3}. 
And their sums are 1, 2, 3, 3, 5, 4 and 6.

Input : arr[] = {1, 2, 3, 4};
        m = 2;
Output : 7
{2}, {4}, {1, 3}, {2, 4}, {1, 2, 3}, {1, 3, 4} 
and {1, 2, 3, 4}

一个简单的解决方案是生成所有可能的子集。对于每个子集,计算其总和,如果总和是m的倍数,则将结果递增1。此方法的时间复杂度为O(2 len ) ,其中len是输入数组的长度。
一个有效的解决方案(小值)基于子集和问题的动态规划解决方案。我们制作一个大小为sum x n的2D数组。

C++
// C++ program which returns the Number of sub sequences
// (or subsets) which are divisible by m.
#include 
using namespace std;
 
// Use Dynamic Programming to find
// sum of subsequences.
int sumSubSequence(vector arr, int len, int m)
{
    // Find sum pf array elements
    int sum = 0;
    for (auto x : arr)
       sum += x;
 
    // dp[i][j] would be > 0 if arr[0..i-1] has
    // a subsequence with sum equal to j.
    vector > dp(len + 1, vector(sum + 1, 0));
 
    // There is always sum equals zero
    for (int i = 0; i <= len; i++)
        dp[i][0]++;
  
    // Fill up the dp table
    for (int i = 1; i <= len; i++) {
 
        dp[i][arr[i - 1]]++;
        for (int j = 1; j <= sum; j++) {
 
            if (dp[i - 1][j] > 0) {
                dp[i][j]++;
                dp[i][j + arr[i - 1]]++;
            }
        }
    }
 
    // Initialize the counter
    int count = 0;
    for (int j = 1; j <= sum; j++)
 
        // Check if the sum exists
        if (dp[len][j] > 0)
 
            // check sum is divisible by m
            if (j % m == 0)
                count += dp[len][j];
 
    return count;
}
 
// Driver Code
int main()
{
    vector arr{ 1, 2, 3 };
    int m = 3;
    int len = arr.size();
    cout << sumSubSequence(arr, len, m) << endl;
    return 0;
}


Java
// Java program which returns the Number of sub sequences
// (or subsets) which are divisible by m.
 
class GFG
{
 
// Use Dynamic Programming to find
// sum of subsequences.
static int sumSubSequence(int []arr, int len, int m)
{
    // Find sum pf array elements
    int sum = 0;
    for (int x : arr)
    {
        sum += x;
    }
 
    // dp[i][j] would be > 0 if arr[0..i-1] has
    // a subsequence with sum equal to j.
    int [][]dp = new int[len + 1][sum + 1];
 
    // There is always sum equals zero
    for (int i = 0; i <= len; i++)
        dp[i][0]++;
 
    // Fill up the dp table
    for (int i = 1; i <= len; i++)
    {
 
        dp[i][arr[i - 1]]++;
        for (int j = 1; j <= sum; j++)
        {
 
            if (dp[i - 1][j] > 0)
            {
                dp[i][j]++;
                dp[i][j + arr[i - 1]]++;
            }
        }
    }
 
    // Initialize the counter
    int count = 0;
    for (int j = 1; j <= sum; j++)
 
        // Check if the sum exists
        if (dp[len][j] > 0)
 
            // check sum is divisible by m
            if (j % m == 0)
                count += dp[len][j];
 
    return count;
}
 
// Driver Code
public static void main(String[] args)
{
    int []arr = { 1, 2, 3 };
    int m = 3;
    int len = arr.length;
    System.out.print(sumSubSequence(arr, len, m) +"\n");
}
}
 
// This code is contributed by Rajput-Ji


Python3
# Python3 program which returns
# the Number of sub sequences
# (or subsets) which are divisible by m.
 
# Use Dynamic Programming to find
# sum of subsequences.
def sumSubSequence(arr, length, m):
 
    # Find sum pf array elements
    summ = 0
    for i in arr:
        summ += i
 
    # dp[i][j] would be > 0 if arr[0..i-1] has
    # a subsequence with sum equal to j.
    dp = [[0 for i in range(summ + 1)]
             for j in range(length + 1)]
 
    # There is always sum equals zero
    for i in range(length + 1):
        dp[i][0] += 1
 
    # Fill up the dp table
    for i in range(1, length + 1):
        dp[i][arr[i - 1]] += 1
        for j in range(1, summ + 1):
            if dp[i - 1][j] > 0:
                dp[i][j] += 1
                dp[i][j + arr[i - 1]] += 1
 
    # Initialize the counter
    count = 0
    for i in range(1, summ + 1):
 
        # Check if the sum exists
        if dp[length][i] > 0:
 
            # check sum is divisible by m
            if i % m == 0:
                count += dp[length][i]
 
    return count
 
# Driver Code
if __name__ == "__main__":
    arr = [1, 2, 3]
    m = 3
    length = len(arr)
    print(sumSubSequence(arr, length, m))
 
# This code is contributed by
# sanjeev2552


C#
// C# program which returns
// the Number of sub sequences
// (or subsets) which are
// divisible by m.
using System;
class GFG{
 
// Use Dynamic Programming
// to find sum of subsequences.
static int sumSubSequence(int []arr,
                          int len,
                          int m)
{
  // Find sum pf array elements
  int sum = 0;
  foreach (int x in arr)
  {
    sum += x;
  }
 
  // dp[i][j] would be > 0 if
  // arr[0..i-1] has a
  // subsequence with sum equal
  // to j.
  int [,]dp = new int[len + 1,
                      sum + 1];
 
  // There is always sum equals
  // zero
  for (int i = 0; i <= len; i++)
    dp[i, 0]++;
 
  // Fill up the dp table
  for (int i = 1; i <= len; i++)
  {
    dp[i, arr[i - 1]]++;
    for (int j = 1; j <= sum; j++)
    {
      if (dp[i - 1, j] > 0)
      {
        dp[i, j]++;
        dp[i, j + arr[i - 1]]++;
      }
    }
  }
 
  // Initialize the counter
  int count = 0;
  for (int j = 1; j <= sum; j++)
 
    // Check if the sum exists
    if (dp[len, j] > 0)
 
      // check sum is divisible
      // by m
      if (j % m == 0)
        count += dp[len, j];
 
  return count;
}
 
// Driver Code
public static void Main(string[] args)
{
  int []arr = {1, 2, 3};
  int m = 3;
  int len = arr.Length;
  Console.Write(
  sumSubSequence(arr,
                 len, m) + "\n");
}
}
 
// This code is contributed by Chitranayal


输出:
3


上述方法的时间复杂度为O(len * sum) ,其中len是数组的大小,sum是数组中所有整数的总和。