这个问题可以通过动态规划(DP)和组合计算来解决。下面是解决思路的详细步骤:
1. 问题分析
我们有 NNN 个甜点,每个甜点有一个固定的喜爱值,同时可以选择使用 MMM 个魔法棒来改变某些甜点的喜爱值为阶乘。目标是通过选择甜点,并可能使用魔法棒,使得这些甜点的喜爱值之和恰好为预期值 SSS。
2. 解题思路
这个问题可以看作一种变体的“背包问题”,但同时需要处理魔法棒的使用,使得状态空间增加。
3. 状态表示
定义一个三维数组 dp[i][j][k],其中:
i表示考虑前 iii 个甜点。j表示当前所选甜点的总喜爱值。k表示已经使用的魔法棒数量。
dp[i][j][k] 表示选择前 iii 个甜点、使得喜爱值之和为 jjj 且使用了 kkk 个魔法棒的方案数。
4. 转移方程
对于第 iii 个甜点,有以下几种选择:
- 不选这个甜点,保持总喜爱值和魔法棒使用数不变。
- 选这个甜点,不使用魔法棒,喜爱值增加
like[i],魔法棒使用数不变。 - 选这个甜点,使用魔法棒,将喜爱值变为
like[i]!,魔法棒使用数加 1(前提是 k+1≤Mk+1 \leq Mk+1≤M)。
因此,状态转移可以描述为:
dp[i][j][k]=dp[i−1][j][k]+dp[i−1][j−like[i]][k]+dp[i−1][j−factorial(like[i])][k−1]dp[i][j][k] = dp[i-1][j][k] + dp[i-1][j - \text{like}[i]][k] + dp[i-1][j - \text{factorial}(\text{like}[i])][k-1]dp[i][j][k]=dp[i−1][j][k]+dp[i−1][j−like[i]][k]+dp[i−1][j−factorial(like[i])][k−1]
其中 factorial(like[i]) 表示 like[i] 的阶乘。
5. 边界条件
- 初始化:
dp[0][0][0] = 1,即不选任何甜点、总和为 0 的方案数为 1。 - 若所求的 jjj 或 kkk 超过目标 SSS 或 MMM,对应的
dp值为 0。
6. 最终答案
遍历 dp[N][S][*] 中所有 * <= M 的情况,将这些方案数累加得到最终答案。
`import math
def factorial(n): """计算 n 的阶乘""" return math.factorial(n)
def solution(n, m, s, like): # 计算所有甜点喜爱值的阶乘(仅计算小于等于 s 的值) factorial_values = {x: factorial(x) for x in set(like) if factorial(x) <= s}
# 初始化 DP 表
dp = [[[0] * (m + 1) for _ in range(s + 1)] for _ in range(n + 1)]
dp[0][0][0] = 1 # 不选任何甜点且总和为 0 的情况
# 填充 DP 表
for i in range(1, n + 1):
for j in range(s + 1):
for k in range(m + 1):
# 不选第 i 个甜点
dp[i][j][k] += dp[i - 1][j][k]
# 选第 i 个甜点但不使用魔法棒
if j >= like[i - 1]:
dp[i][j][k] += dp[i - 1][j - like[i - 1]][k]
# 选第 i 个甜点并使用魔法棒
if k > 0 and like[i - 1] in factorial_values:
fact_value = factorial_values[like[i - 1]]
if j >= fact_value:
dp[i][j][k] += dp[i - 1][j - fact_value][k - 1]
# 统计结果
result = sum(dp[n][s][k] for k in range(m + 1))
return result
测试样例
print(solution(3, 2, 6, [1, 2, 3])) # 输出: 5 print(solution(3, 1, 1, [1, 1, 1])) # 输出: 6 print(solution(5, 3, 24, [1, 2, 3, 4, 5])) # 输出: 1 print(solution(4, 0, 10, [1, 3, 3, 3])) # 输出: 1 print(solution(6, 1, 35, [5, 5, 5, 5, 5, 5])) # 输出: 0 `
-
solution函数接收参数 nnn, mmm, sss, 和甜点的喜爱值列表like。 -
通过
factorial_values预计算每个甜点喜爱值的阶乘(在合理范围内)。 -
使用三重循环更新 DP 表
dp。 -
最后,将
dp[n][s][*]中使用不同魔法棒数量(不超过 mmm)的方案数累加,得到最终答案。