Skip to content
Related Articles

Related Articles

Improve Article

Number of subsets with sum divisible by M | Set 2

  • Difficulty Level : Hard
  • Last Updated : 13 May, 2021
Geek Week

Given an array arr[] of N integers and an integer M, the task is to find the number of non-empty subsequences such that the sum of the subsequence is divisible by M.

Examples:  

Input: arr[] = {1, 2, 3}, M = 1 
Output:
Number of non-empty subsets of this array are 7. 
Since m = 1, m will divide all the possible subsets.
Input: arr[] = {1, 2, 3}, M = 2 
Output: 3  

Approach: A dynamic programming-based approach with O(N * SUM) time complexity where N is the length of the array and SUM is the sum of all the array elements has been discussed in this article.
In this article, an improvement over the previous approach will be discussed. Instead of the sum as one of the states of DP, (sum % m) will be used as one of the states of the DP as it is sufficient. Thus, the time complexity boils down to O(m * N).
Recurrence relation: 

dp[i][curr] = dp[i + 1][(curr + arr[i]) % m] + dp[i + 1][curr]  



Let’s define the states now, dp[i][curr] simply means number of subsets of the sub-array arr[i…N-1] such that (sum of its element + curr) % m = 0.

Below is the implementation of the above approach:  

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define maxN 20
#define maxM 10
 
// To store the states of DP
int dp[maxN][maxM];
bool v[maxN][maxM];
 
// Function to find the required count
int findCnt(int* arr, int i, int curr, int n, int m)
{
    // Base case
    if (i == n) {
        if (curr == 0)
            return 1;
        else
            return 0;
    }
 
    // If the state has been solved before
    // return the value of the state
    if (v[i][curr])
        return dp[i][curr];
 
    // Setting the state as solved
    v[i][curr] = 1;
 
    // Recurrence relation
    return dp[i][curr] = findCnt(arr, i + 1,
                                 curr, n, m)
                         + findCnt(arr, i + 1,
                                   (curr + arr[i]) % m,
                                   n, m);
}
 
// Driver code
int main()
{
    int arr[] = { 3, 3, 3, 3 };
    int n = sizeof(arr) / sizeof(int);
    int m = 6;
 
    cout << findCnt(arr, 0, 0, n, m) - 1;
 
    return 0;
}

Java




// Java implementation of the approach
class GFG
{
static int maxN = 20;
static int maxM = 10;
 
// To store the states of DP
static int [][]dp = new int[maxN][maxM];
static boolean [][]v = new boolean[maxN][maxM];
 
// Function to find the required count
static int findCnt(int[] arr, int i,
                   int curr, int n, int m)
{
    // Base case
    if (i == n)
    {
        if (curr == 0)
            return 1;
        else
            return 0;
    }
 
    // If the state has been solved before
    // return the value of the state
    if (v[i][curr])
        return dp[i][curr];
 
    // Setting the state as solved
    v[i][curr] = true;
 
    // Recurrence relation
    return dp[i][curr] = findCnt(arr, i + 1,
                                 curr, n, m) +
                         findCnt(arr, i + 1,
                                (curr + arr[i]) % m,
                                 n, m);
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { 3, 3, 3, 3 };
    int n = arr.length;
    int m = 6;
 
    System.out.println(findCnt(arr, 0, 0, n, m) - 1);
}
}
 
// This code is contributed by 29AjayKumar

Python3




# Python3 implementation of the approach
maxN = 20
maxM = 10
 
# To store the states of DP
dp = [[0 for i in range(maxN)]
         for i in range(maxM)]
v = [[0 for i in range(maxN)]
        for i in range(maxM)]
 
# Function to find the required count
def findCnt(arr, i, curr, n, m):
     
    # Base case
    if (i == n):
        if (curr == 0):
            return 1
        else:
            return 0
 
    # If the state has been solved before
    # return the value of the state
    if (v[i][curr]):
        return dp[i][curr]
 
    # Setting the state as solved
    v[i][curr] = 1
 
    # Recurrence relation
    dp[i][curr] = findCnt(arr, i + 1,
                          curr, n, m) + \
                  findCnt(arr, i + 1,
                         (curr + arr[i]) % m, n, m)
    return dp[i][curr]
 
# Driver code
arr = [3, 3, 3, 3]
n = len(arr)
m = 6
 
print(findCnt(arr, 0, 0, n, m) - 1)
 
# This code is contributed by Mohit Kumar

C#




// C# implementation of the approach
using System;
 
class GFG
{
    static int maxN = 20;
    static int maxM = 10;
     
    // To store the states of DP
    static int [,]dp = new int[maxN, maxM];
    static bool [,]v = new bool[maxN, maxM];
     
    // Function to find the required count
    static int findCnt(int[] arr, int i,
                       int curr, int n, int m)
    {
        // Base case
        if (i == n)
        {
            if (curr == 0)
                return 1;
            else
                return 0;
        }
     
        // If the state has been solved before
        // return the value of the state
        if (v[i, curr])
            return dp[i, curr];
     
        // Setting the state as solved
        v[i, curr] = true;
     
        // Recurrence relation
        return dp[i, curr] = findCnt(arr, i + 1,
                                     curr, n, m) +
                             findCnt(arr, i + 1,
                                    (curr + arr[i]) % m, n, m);
    }
     
    // Driver code
    public static void Main()
    {
        int []arr = { 3, 3, 3, 3 };
        int n = arr.Length;
        int m = 6;
     
        Console.WriteLine(findCnt(arr, 0, 0, n, m) - 1);
    }
}
 
// This code is contributed by kanugargng

Javascript




<script>
 
// Javascript implementation of the approach
var maxN = 20
var maxM = 10
 
// To store the states of DP
var dp = Array.from(Array(maxN), () => Array(maxM));
var v = Array.from(Array(maxN), () => Array(maxM));
 
// Function to find the required count
function findCnt(arr, i, curr, n, m)
{
    // Base case
    if (i == n) {
        if (curr == 0)
            return 1;
        else
            return 0;
    }
 
    // If the state has been solved before
    // return the value of the state
    if (v[i][curr])
        return dp[i][curr];
 
    // Setting the state as solved
    v[i][curr] = 1;
 
    // Recurrence relation
    dp[i][curr] = findCnt(arr, i + 1,
                                 curr, n, m)
                         + findCnt(arr, i + 1,
                                   (curr + arr[i]) % m,
                                   n, m);
 
    return dp[i][curr];
}
 
// Driver code
var arr = [3, 3, 3, 3];
var n = arr.length;
var m = 6;
document.write( findCnt(arr, 0, 0, n, m) - 1);
 
</script>
Output: 
7

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :