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