Count of Sub-Multisets With Bounded Sum
Problem Description​
You are given a 0-indexed array nums
of non-negative integers, and two integers l
and r
.
Return the count of sub-multisets within nums
where the sum of elements in each subset falls within the inclusive range of [l, r]
.
Since the answer may be large, return it modulo 10^9 + 7.
A sub-multiset is an unordered collection of elements of the array in which a given value x can occur 0, 1, ..., occ[x] times, where occ[x]
is the number of occurrences of x in the array.
Note that:
- Two sub-multisets are the same if sorting both sub-multisets results in identical multisets.
- The sum of an empty multiset is 0.
Examples​
Example 1:
Input: nums = [1,2,2,3], l = 6, r = 6
Output: 1
Explanation: The only subset of nums that has a sum of 6 is {1, 2, 3}.
Example 2:
Input: nums = [2,1,4,2,7], l = 1, r = 5
Output: 7
Explanation: The subsets of nums that have a sum within the range [1, 5] are {1}, {2}, {4}, {2, 2}, {1, 2}, {1, 4}, and {1, 2, 2}.
Example 3:
Input: nums = [1,2,1,3,5,2], l = 3, r = 5
Output: 9
Explanation: The subsets of nums that have a sum within the range [3, 5] are {3}, {5}, {1, 2}, {1, 3}, {2, 2}, {2, 3}, {1, 1, 2}, {1, 1, 3}, and {1, 2, 2}.
Constraints​
1 <= nums.length <= 2 * 10^4
0 <= nums[i] <= 2 * 10^4
Sum of nums does not exceed 2 * 10^4.
0 <= l <= r <= 2 * 10^4
Approach​
dp[i] is the number of unique sorted multisets of sum i lets say that we use a new number, a that occurs c times within the array we can add a 1 to c times to every multiset to create new ones, so the dp transition will look like dp[i] += dp[i - a] + dp[i - a * 2] + ... + dp[i - a * c]
Since the sum of c across all a is n, doing dp like this will result in n^2 time complexity. We can speed up the update for each pair of a, c by using sliding window. We do this by we want to add to dp[i] dp[i - a] + dp[i - a * 2] + ... + dp[i - a * c].
Note that the stuff we add to dp[i - a] is very similar: dp[i - a * 2] + dp[i - a * 3] + ... + dp[i - a * (c + 1)] dp[i - a] got removed, and dp[i - a * (c + 1)] got added once you know the amount to add for dp[i], it takes constant time to compute the amount to add for dp[i - a].
I claim that when sped up, each pair will only take O(n) time to process and since the number of unique a is at most 200.
C++​
typedef long long ll;
const ll MOD = 1e9 + 7;
class Solution {
public:
int countSubMultisets(vector<int>& nums, int l, int r) {
const ll N = 2e4;
vector<ll> dp(N + 1);
map<ll,ll> m;
dp[0] = 1;
m[0] = 1;
for(auto x : nums) {
m[x]++;
}
ll mult = m[0]; m.erase(0);
for(auto x : m) {
//{a, c}
ll a = x.first;
ll c = x.second;
vector<ll> help(N + 1);
for(int i = 1; i <= N; i++) {
ll sum = 0;
if(i - a >= 0) {
sum += dp[i-a];
sum += help[i-a];
}
if(i - a * (c + 1) >= 0) {
sum -= dp[i - a * (c + 1)];
}
help[i] = (sum + MOD) % MOD;
}
for(int i = 0; i <= N; i++) {
dp[i] += help[i];
if(dp[i] >= MOD) dp[i] -= MOD;
}
}
ll sum = 0;
for(int i = l; i <= r; i++) {
sum += dp[i];
if(sum >= MOD) sum -= MOD;
}
return sum * mult % MOD;
}
};
Complexity​
- Time complexity:
- Space complexity: