Open In App

Number of subsets with sum divisible by m

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given an array of integers, find a number of subsequences such that the sum of the subsequence is divisible by m. It is given that sum of array elements is small. 
Examples: 

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}

A simple solution is to generate all possible subsets. For every subset, compute its sum, and if the sum is multiple of m, increment result by 1. The time complexity of this approach is O(2len) where len is the length of the input array.

An efficient solution (for small values) is based on Dynamic Programming solution of subset sum problem. We make a 2D array of size sum x n. 

Implementation:

C++




// C++ program which returns the Number of sub sequences
// (or subsets) which are divisible by m.
#include <bits/stdc++.h>
using namespace std;
 
// Use Dynamic Programming to find
// sum of subsequences.
int sumSubSequence(vector<int> arr, int len, int m)
{
    // Find sum of 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<vector<int> > dp(len + 1, vector<int>(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<int> 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 of 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 of 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 of 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


Javascript




<script>
// Javascript program which returns the Number of sub sequences
// (or subsets) which are divisible by m.
 
// Use Dynamic Programming to find
// sum of subsequences.
function sumSubSequence(arr,len,m)
{
    // Find sum of array elements
    let sum = 0;
    for (let x=0;x<arr.length;x++)
    {
        sum += arr[x];
    }
  
    // dp[i][j] would be > 0 if arr[0..i-1] has
    // a subsequence with sum equal to j.
    let dp = new Array(len + 1);
    for(let i=0;i<dp.length;i++)
    {
        dp[i]=new Array(sum+1);
        for(let j=0;j<dp[i].length;j++)
        {
            dp[i][j]=0;
        }
    }
  
    // There is always sum equals zero
    for (let i = 0; i <= len; i++)
        dp[i][0]++;
  
    // Fill up the dp table
    for (let i = 1; i <= len; i++)
    {
  
        dp[i][arr[i - 1]]++;
        for (let j = 1; j <= sum; j++)
        {
  
            if (dp[i - 1][j] > 0)
            {
                dp[i][j]++;
                dp[i][j + arr[i - 1]]++;
            }
        }
    }
  
    // Initialize the counter
    let count = 0;
    for (let 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
let arr=[ 1, 2, 3];
let m = 3;
let len = arr.length;
document.write(sumSubSequence(arr, len, m) +"<br>");
 
// This code is contributed by avanitrachhadiya2155
</script>


Output

3










The time complexity of the above approach is O(len*sum) where len is the size of the array and sum is the sum of all the integers in the array.

Efficient approach : Space optimization

In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.

Implementation steps:

  • Create a 1D vector dp of size Sum+1 and initialize it with 0
  • Initialize base case dp[0] = 1.  
  • Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
  • Now Create a temporary 1d vector temp used to store the current values from previous computations.
  • After every iteration assign the value of temp to dp for further iteration.
  • Initialize a variable count to store the final answer and update it by iterating through the Dp.
  • At last return and print the final answer stored in count.

Implementation: 

C++




// C++ code for above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Use Dynamic Programming to find
// sum of subsequences.
int sumSubSequence(vector<int> arr, int len, int m)
{
    // Find sum of array elements
    int sum = 0;
    for (auto x : arr)
        sum += x;
 
    // initialize Dp to store computations of subproblems
    vector<int> dp(sum + 1, 0);
 
    // Base Case
    dp[0] = 1;
 
    // iterate over subproblem to get the current
    // value from previous computations
    for (int i = 1; i <= len; i++) {
 
        // create new temporary vector to get the
        // reference of current row of DP matrix
        vector<int> temp = dp;
        for (int j = 1; j <= sum; j++) {
            if (dp[j - arr[i - 1]] > 0)
                temp[j] += dp[j - arr[i - 1]];
        }
 
        // assigning values to iterate further
        dp = temp;
    }
 
    // to store final answer
    int count = 0;
    for (int j = 1; j <= sum; j++) {
        if (dp[j] > 0 && j % m == 0)
            count += dp[j];
    }
 
    // return answer
    return count;
}
 
// Driver code
int main()
{
    vector<int> arr{ 1, 2, 3 };
    int m = 3;
    int len = arr.size();
    cout << sumSubSequence(arr, len, m) << endl;
    return 0;
}


Java




import java.util.ArrayList;
import java.util.List;
 
public class Main {
    // Use Dynamic Programming to find sum of subsequences.
    public static int sumSubSequence(List<Integer> arr, int len, int m) {
        // Find sum of array elements
        int sum = 0;
        for (int x : arr)
            sum += x;
 
        // Initialize dp array to store computations of subproblems
        int[] dp = new int[sum + 1];
 
        // Base Case
        dp[0] = 1;
 
        // Iterate over subproblems to get the current value
        // from previous computations
        for (int i = 0; i < len; i++) {
            // Create a new temporary array to get the reference
            // of the current row of the dp matrix
            int[] temp = dp.clone();
            for (int j = 0; j <= sum; j++) {
                if (dp[j] > 0 && j + arr.get(i) <= sum)
                    temp[j + arr.get(i)] += dp[j];
            }
 
            // Assign values to iterate further
            dp = temp;
        }
 
        // Initialize count to store the final answer
        int count = 0;
        for (int j = m; j <= sum; j += m) {
            count += dp[j];
        }
 
        // Return the answer
        return count;
    }
 
    // Driver code
    public static void main(String[] args) {
        List<Integer> arr = List.of(1, 2, 3);
        int m = 3;
        int len = arr.size();
        System.out.println(sumSubSequence(arr, len, m));
    }
}


Python3




# Use Dynamic Programming to find sum of subsequences.
def sumSubSequence(arr, len, m):
    # Find sum of array elements
    sum = 0
    for i in range(len):
        sum += arr[i]
 
    # Initialize dp array to store computations of subproblems
    dp = [0] * (sum + 1)
 
    # Base Case
    dp[0] = 1
 
    # Iterate over subproblems to get the current value
    # from previous computations
    for i in range(1, len + 1):
        # Create a new temporary array to get the reference
        # of the current row of the dp matrix
        temp = dp[:]
        for j in range(1, sum + 1):
            if dp[j - arr[i - 1]] > 0:
                temp[j] += dp[j - arr[i - 1]]
 
        # Assign values to iterate further
        dp = temp
 
    # Initialize count to store the final answer
    count = 0
    for j in range(1, sum + 1):
        if dp[j] > 0 and j % m == 0:
            count += dp[j]
 
    # Return the answer
    return count
 
 
# Driver code to test above function
arr = [1, 2, 3]
m = 3
len = len(arr)
print(sumSubSequence(arr, len, m))
 
# THIS CODE IS CONTRIBUTED BY KANCHAN AGARWAL


C#




using System;
using System.Collections.Generic;
 
public class GFG {
    // Use Dynamic Programming to find sum of subsequences.
    static int SumSubSequence(List<int> arr, int len, int m)
    {
        // Find sum of array elements
        int sum = 0;
        foreach(var x in arr) sum += x;
 
        // Initialize Dp to store computations of
        // subproblems
        int[] dp = new int[sum + 1];
 
        // Base Case
        dp[0] = 1;
 
        // Iterate over subproblems to get the current
        // value from previous computations
        for (int i = 1; i <= len; i++) {
            for (int j = sum; j >= arr[i - 1]; j--) {
                if (dp[j - arr[i - 1]] > 0)
                    dp[j] += dp[j - arr[i - 1]];
            }
        }
 
        // To store final answer
        int count = 0;
        for (int j = 1; j <= sum; j++) {
            if (dp[j] > 0 && j % m == 0)
                count += dp[j];
        }
 
        // Return answer
        return count;
    }
 
    public static void Main(string[] args)
    {
        List<int> arr = new List<int>{ 1, 2, 3 };
        int m = 3;
        int len = arr.Count;
        Console.WriteLine(SumSubSequence(arr, len, m));
    }
}


Javascript




// Javascript code for above approach
 
// Use Dynamic Programming to find sum of subsequences.
function sumSubSequence(arr, len, m) {
    // Find sum of array elements
    let sum = 0;
    for (let i = 0; i < len; i++) {
        sum += arr[i];
    }
 
    // Initialize dp array to store computations of subproblems
    let dp = new Array(sum + 1).fill(0);
 
    // Base Case
    dp[0] = 1;
 
    // Iterate over subproblems to get the current value
    // from previous computations
    for (let i = 1; i <= len; i++) {
        // Create a new temporary array to get the reference
        // of the current row of the dp matrix
        let temp = [...dp];
        for (let j = 1; j <= sum; j++) {
            if (dp[j - arr[i - 1]] > 0) {
                temp[j] += dp[j - arr[i - 1]];
            }
        }
 
        // Assign values to iterate further
        dp = temp;
    }
 
    // Initialize count to store the final answer
    let count = 0;
    for (let j = 1; j <= sum; j++) {
        if (dp[j] > 0 && j % m === 0) {
            count += dp[j];
        }
    }
 
    // Return the answer
    return count;
}
 
// Driver code to test above function
let arr = [1, 2, 3];
let m = 3;
let len = arr.length;
console.log(sumSubSequence(arr, len, m));
 
// THIS CODE IS CONTRIBUTED BY KANCHAN AGARWAL


Output

3










Time Complexity : O(len * Sum)
Auxiliary Space : O(Sum)



Last Updated : 29 Aug, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads