LC 2518. 好分区的数目
https://leetcode.cn/contest/weekly-contest-325/problems/number-of-great-partitions/
这题稍微有点绕。我们可以计算出一个分区上 `dp[i][k]` (表示考虑到第i个元素,所有元素加起来和为k)的数量,但是我们却很难计算出 `分区所有元素和>=k` 的情况,因为这个动态规划的数量太大了。
换个思路,可以使用另外一个角度来进行计算:
- (G1, G2)所有可能的组合数量 `(2 ** n)`
- `sum(G1) < k` 的所有可能数量,假设是 `X`
- `sum(G2) < k` 的所有可能数量一样是 `X`
- `sum(G1) < k & sum(G2) < k` 的所有可能数量是 `Y` 的话
- 那么 `sum(G1) >=k & sum(G2)>=k` 的数量就是 `(2**n) - X - X + Y`
其中X, Y都可以使用一个动态规划计算出来。下面代码里面可能MOD没有怎么处理好,但是可以通过测试用例。
class Solution:
def countPartitions(self, nums: List[int], k: int) -> int:
n = len(nums)
def precompute():
dp = [[0] * (k) for _ in range(n + 1)]
dp[0][0] = 1
for i in range(n):
for j in range(0, k):
j2 = nums[i] + j
if j2 < k:
dp[i + 1][j2] += dp[i][j]
dp[i + 1][j] += dp[i][j]
return dp
def pow(a, b, MOD):
ans = 1
while b:
if b & 0x1:
ans = ans * a
ans = ans % MOD
a = (a * a) % MOD
b = b >> 1
return ans
# (G1, G2) = (2**n) % MOD
# G1<k = dp[n][j] j in [0, k)
# G2<k = dp[n][j] j in [0, k)
# G1<k & G2<k = dp[n][j] j in [0,k) and (SUM-j) in [0,k)
# (G1,G2) - (G1<k) - (G2<k) + (G1<k & G2<k) = (G1>=k & G2>=k)
dp = precompute()
SUM = sum(nums)
MOD = 10 ** 9 + 7
ans = pow(2, n, MOD)
for j in range(0, k):
ans -= 2 * dp[n][j]
for j in range(0, k):
if (SUM - j) < k:
ans += dp[n][j]
return ans % MOD