Count number of distinct sum subsets within given range

Given a set S of N numbers and a range specified by two numbers L (Lower Bound) and R (Upper Bound). Find the number of distinct values of all possible sums of some subset of S that lie between the given range.

Examples :

Input : S = { 1, 2, 2, 3, 5 }, L = 1 and R = 5
Output : 5
Explanation :  Every number between 
1 and 5 can be made out using some subset of S.
{1 as 1, 2 as 2, 3 as 3, 4 as 2 + 2 and 5 as 5} 

Input : S = { 2, 3, 5 }, L = 1 and R = 7
Output : 4
Explanation :  Only 4 numbers between 
1 and 7 can be made out, i.e. {2, 3, 5, 7}. 
3 numbers which are {1, 4, 6} can't be made out in any way.


Prerequisites : Bitset | Bit Manipulation

Method 1(Simple) : A naive approach is to generate all possible subsets of given set, calculate their sum subset wise and push them into a hashmap. Iterate over the complete given range and count the numbers which exists in the hashmap.

Method 2(Efficient) : An efficient way to solve this problem is by using bitset of size 105. Update the bitset for every element X by left shifting the bitset and doing bitwise OR with previous bitset so that the bitset at the new possible sums become 1. Then by using the concept of Prefix Sums, precompute the required count of numbers between 1 and i for prefix[1..i] to answer each query in O(1) if there are more than query being asked simultaneously. For a query L and R, answer would be simply prefix[R] – prefix[L – 1]

For e.g. S = { 2, 3, 5 }, L = 1 and R = 7
Considering a bitset of size 32 for simplicity. Initially 1 is at 0th position of bitset
00000000000000000000000000000001
For incoming 2, left shifting the bitset by 2 and doing OR with previous bitset
00000000000000000000000000000101
Similarly for 3,
00000000000000000000000000101101
for 5,
00000000000000000000010110101101
This final bitset contains 1 at those positions(possible sums) which can be made out using some
subset of S. Hence between position 1 and 7, there are 4 set bits, thus the required answer.

Below is the implementation of above approach in C++ :

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP Program to count the number
// distinct values of sum of some
// subset in a range
#include <bits/stdc++.h>
  
using namespace std;
  
// Constant size for bitset
#define SZ 100001
  
int countOfpossibleNumbers(int S[], int N, 
                           int L, int R)
{
    // Creating a bitset of size SZ
    bitset <SZ> BS;
      
    // Set 0th position to 1
    BS[0] = 1;
      
    // Build the bitset
    for (int i = 0; i < N; i++) {
          
        // Left shift the bitset for each
        // element and taking bitwise OR
        // with previous bitset
        BS = BS | (BS << S[i]);
    }
      
    int prefix[SZ];
      
    // Intializing the prefix array to zero
    memset(prefix, 0, sizeof(prefix));
      
    // Build the prefix array
    for (int i = 1; i < SZ; i++) {
        prefix[i] = prefix[i - 1] + BS[i];
    }
      
    // Answer the given query
    int ans = prefix[R] - prefix[L - 1];
      
    return ans;
}
  
// Driver Code to test above functions
int main() 
{
    int S[] = { 1, 2, 3, 5, 7 };
    int N = sizeof(S) / sizeof(S[0]);
      
    int L = 1, R = 18;
      
    cout << countOfpossibleNumbers(S, N, L, R);
          
    return 0;

chevron_right


Output:

18

Time Complexity : O(S*Z) where S*Z is the maximum sum for given constraints, i.e. 105



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.