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++ 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 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 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# 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 |
<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> |
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++ 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;
} |
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));
}
} |
# 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 |
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 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 |
3
Time Complexity : O(len * Sum)
Auxiliary Space : O(Sum)