Subset Sum Queries in a Range using Bitset

Given an array[] of N positive integers and M queries. Each query consists of two integers L and R represented by a range. For each query, find the count of numbers that lie in the given range which can be expressed as the sum of any subset of given array.

Prerequisite : Subset Sum Queries using Bitset
Examples:

Input : arr[] = { 1, 2, 2, 3, 5 }, M = 4
L = 1, R = 2
L = 1, R = 5
L = 3, R = 6
L = 9, R = 30
Output :
2
5
4
5
Explanation : For the first query, in range [1, 2] all numbers i.e. 1 and 2 can be expressed as a subset sum, 1 as 1, 2 as 2. For the second query, in range [1, 5] all numbers i.e. 1, 2, 3, 4 and 5 can be expressed as subset sum, 1 as 1, 2 as 2, 3 as 3, 4 as 2 + 2 or 1 + 3, 5 as 5. For the third query, in range [3, 6], all numbers i.e. 3, 4, 5 and 6 can be expressed as subset sum. For the last query, only numbers 9, 10, 11, 12, 13 can be expressed as subset sum, 9 as 5 + 2 + 2, 10 as 5 + 2 + 2 + 1, 11 as 5 + 3 + 2 + 1, 12 as 5 + 3 + 2 + 2 and 13 as 5 + 3 + 2 + 2 + 1.



Approach : The idea is to use a bitset and iterate over the array to represent all possible subset sums. The current state of bitset is defined by ORing it with the previous state of bitset left shifted X times where X is the current element processed in the array. To answer the queries in O(1) time, we can precompute the count of numbers upto every number and for a range [L, R], answer would be pre[R] – pre[L – 1], where pre[] is the precomputed array.

Below is the implementation of above approach.

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP Program to answer subset
// sum queries in a given range
#include <bits/stdc++.h>
using namespace std;
  
const int MAX = 1001;
bitset<MAX> bit;
  
// precomputation array
int pre[MAX];
  
// structure to represent query
struct que {
    int L, R;
};
  
void answerQueries(int Q, que Queries[], int N,
                   int arr[])
{
    // Setting bit at 0th position as 1
    bit[0] = 1;
    for (int i = 0; i < N; i++)
        bit |= (bit << arr[i]);
  
    // Precompute the array
    for (int i = 1; i < MAX; i++)
        pre[i] = pre[i - 1] + bit[i];
  
    // Answer Queries
    for (int i = 0; i < Q; i++) {
        int l = Queries[i].L;
        int r = Queries[i].R;
        cout << pre[r] - pre[l - 1] << endl;
    }
}
  
// Driver Code to test above function
int main()
{
    int arr[] = { 1, 2, 2, 3, 5 };
    int N = sizeof(arr) / sizeof(arr[0]);
    int M = 4;
    que Queries[M];
    Queries[0].L = 1, Queries[0].R = 2;
    Queries[1].L = 1, Queries[1].R = 5;
    Queries[2].L = 3, Queries[2].R = 6;
    Queries[3].L = 9, Queries[3].R = 30;
    answerQueries(M, Queries, N, arr);
    return 0;
}

chevron_right


Output:

2
5
4
5

Time Complexity : Each query can be answered in O(1) time and precomputation requires O(MAX) time.



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.