第 117 场双周赛(容斥原理,记忆化搜索,排序)
本题我们采用隔板法+容斥原理来解决
合格总方案数 = 总方案书 - 不合理的方案数 = 不考虑limit的方案数 - 不合法方案数(至少有一个小朋友 > limit)
任意方案数 n个小球放到3个盒子中 -> n + 2个位置,选两个位置放隔板剩下位置放球 c(n + 2, 2)
三个小朋友为:甲乙丙
小朋友甲(乙丙)>limit 的方案数 c(n - (limit+1) + 2, 2)
小朋友甲乙(甲丙,乙丙)> limit 方案数 c(n - (limit + 1) * 2 + 2, 2)
下朋友甲乙丙三个都 > limit 的方案数 c(n - (limit + 1) * 3 + 2, 2)
def c2(n: int) -> int: return n * (n - 1) // 2 if n > 1 else 0 class Solution: def distributeCandies(self, n: int, limit: int) -> int: return c2(n + 2) - 3 * c2(n - (limit + 1) + 2) + 3 * c2(n - 2 * (limit + 1) + 2) - c2(n - 3 * (limit + 1) + 2)
解法1:dfs
本题可以抽象为一个分组背包问题方案数
n组物品,每组可以选择a - z至少选择1个'l', 1个t,2个e的方案数
MOD = 10 ** 9 + 7 @cache def dfs(i: int, L: int, t: int, e: int) -> int: if i == 0: return 1 if L == 0 and t == 0 and e == 0 else 0 res = dfs(i - 1, 0, t, e) res += dfs(i - 1, L, 0, e) res += dfs(i - 1, L, t, max(0, e - 1)) res += dfs(i - 1, L, t, e) * 23 return res % MOD class Solution: def stringCount(self, n: int) -> int: return dfs(n, 1, 1, 2)
解法2: 容斥原理
与上一题类似,详细理解 灵神的详细讲解
class Solution: def stringCount(self, n: int) -> int: MOD = 10 ** 9 + 7 return ( pow(26, n, MOD) -pow(25, n - 1, MOD) * (75 + n) +pow(24, n - 1, MOD) * (72 + n * 2) -pow(23, n - 1, MOD) * (23 + n) ) % MOD
class Solution { public: long long maxSpending(vector<vector<int>>& values) { int n = values.size(), m = values[0].size(); vector<int> arr(n * m + 1, 0); int idx = 0; for(int i = 0; i < n; i ++ ) { for(int j = 0; j < m; j ++ ) { arr[idx ++ ] = values[i][j]; } } sort(arr.begin(), arr.end()); long long res = 0; for(int i = 0; i <= idx; i ++ ) { res += (long long)i * arr[i]; } return res; } };