You are given a 0-indexed array nums of non-negative integers, and two integers l and r.
Return thecount of sub-multisets withinnumswhere 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.
Input: nums =[2,1,4,2,7], l =1, r =5Output: 7Explanation: 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}.
Input: nums =[1,2,1,3,5,2], l =3, r =5Output: 9Explanation: 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}.
This is a variation of the bounded knapsack problem. For each unique value in nums, we can use it up to its frequency. We use dynamic programming to count the number of multisets (with repetitions up to the frequency) whose sum is in [l, r].
classSolution {
publicintcountSubMultisets(int[] nums, int l, int r) {
int MOD = 1_000_000_007;
Map<Integer, Integer> freq =new HashMap<>();
for (int x : nums) freq.put(x, freq.getOrDefault(x, 0) + 1);
int[] dp =newint[r+1]; dp[0]= 1;
for (var e : freq.entrySet()) {
int val = e.getKey(), cnt = e.getValue();
int[] ndp = dp.clone();
for (int rem = 1; rem <= cnt; rem++) {
for (int s = r; s >= val*rem; s--) {
ndp[s]= (ndp[s]+ dp[s - val*rem]) % MOD;
}
}
dp = ndp;
}
int ans = 0;
for (int s = l; s <= r; s++) ans = (ans + dp[s]) % MOD;
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution {
funcountSubMultisets(nums: IntArray, l: Int, r: Int): Int {
val MOD = 1_000_000_007
val freq = nums.groupingBy { it }.eachCount()
var dp = IntArray(r+1); dp[0] = 1for ((val_, cnt) in freq) {
val ndp = dp.copyOf()
for (rem in1..cnt) {
for (s in r downTo val_ * rem) {
ndp[s] = (ndp[s] + dp[s - val_ * rem]) % MOD
}
}
dp = ndp
}
var ans = 0for (s in l..r) ans = (ans + dp[s]) % MOD
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
classSolution:
defcountSubMultisets(self, nums: list[int], l: int, r: int) -> int:
MOD =10**9+7from collections import Counter
freq = Counter(nums)
dp = [0] * (r+1)
dp[0] =1for val, cnt in freq.items():
ndp = dp[:]
for rem in range(1, cnt+1):
for s in range(r, val*rem-1, -1):
ndp[s] = (ndp[s] + dp[s - val*rem]) % MOD
dp = ndp
return sum(dp[s] for s in range(l, r+1)) % MOD
⏰ Time complexity: O(n * r), where n is the number of unique values and r is the upper bound for the sum. For each value, we update the dp array up to r for each count.