title
给你一个长度为 n 的整数数组 nums 和一个 正 整数 k 。
一个整数数组的 能量 定义为和 等于 k 的子序列的数目。
请你返回 nums 中所有子序列的 能量和 。
由于答案可能很大,请你将它对 109 + 7 取余 后返回。
示例 1:
输入: nums = [1,2,3], k = 3
输出: 6
解释:
总共有 5 个能量不为 0 的子序列:
- 子序列
[***1***,***2***,***3***]有2个和为3的子序列:[1,2,***3\***]和[***1\***,***2\***,3]。 - 子序列
[***1***,2,***3***]有1个和为3的子序列:[1,2,***3\***]。 - 子序列
[1,***2***,***3***]有1个和为3的子序列:[1,2,***3\***]。 - 子序列
[***1***,***2***,3]有1个和为3的子序列:[***1\***,***2\***,3]。 - 子序列
[1,2,***3***]有1个和为3的子序列:[1,2,***3\***]。
所以答案为 2 + 1 + 1 + 1 + 1 = 6 。
示例 2:
输入: nums = [2,3,3], k = 5
输出: 4
解释:
总共有 3 个能量不为 0 的子序列:
- 子序列
[***2***,***3***,***3***]有 2 个子序列和为5:[***2\***,3,***3\***]和[***2\***,***3\***,3]。 - 子序列
[***2***,3,***3***]有 1 个子序列和为5:[***2\***,3,***3\***]。 - 子序列
[***2***,***3***,3]有 1 个子序列和为5:[***2\***,***3\***,3]。
所以答案为 2 + 1 + 1 = 4 。
示例 3:
输入: nums = [1,2,3], k = 7
输出: 0
解释:不存在和为 7 的子序列,所以 nums 的能量和为 0 。
提示:
1 <= n <= 1001 <= nums[i] <= 1041 <= k <= 100
solution
动态规划,表示考虑前i 个物品,所选物品体积和是 j,选了 c 个物品的方案数。
这里不能用前i个物品,同时第i个结尾的用法。如果没有对第i个结尾有需要就可以不用,否则会复杂度再乘以个n。
时间复杂度O(nnk)
class Solution:
def sumOfPower(self, nums: List[int], k: int) -> int:
MOD = int(1e9 + 7)
import functools
@functools.lru_cache(None)
def f(i, s, l):
# print((i,s,l))
if i == 0:
if s == 0 and l == 0:
return 1
return 0
v = nums[i - 1]
res = 0
# select
if s - v >= 0 and l - 1 >= 0:
res += f(i - 1, s - v, l - 1)
# not
res += f(i - 1, s, l)
res %= MOD
return res
n = len(nums)
# dp = [[0 for _ in range(k + 1)] for _ in range(n + 1)]
# dp[0][0] = 1
# for i in range(n):
# v = nums[i]
# for l in range(n, 0, -1):
# for s in range(k, 0, -1):
# if s - v >= 0:
# dp[l][s] += dp[l - 1][s - v]
# p = 1
# ans = 0
# for l in range(len(nums), 0, -1):
# count = dp[l][k]
# ans += count * p
# p *= 2
# p %= MOD
# ans %= MOD
# return ans
#
# n = len(nums)
p = 1
ans = 0
for l in range(len(nums), 0, -1):
count = f(n, k, l)
ans += count * p
p *= 2
p %= MOD
ans %= MOD
f.cache_clear()
return ans