魔法甜点之和:小包的新挑战解析 | 豆包MarsCode AI刷题

60 阅读4分钟

题目详解:魔法甜点之和:小包的新挑战

问题理解

本题的核心目标是找到一种方案,使得通过选择一些甜点并可能使用魔法棒(将甜点的喜爱值变为其阶乘),使得这些甜点的喜爱值之和恰好等于给定的预期值 S。每个甜点只能使用一次魔法棒,也可以完全不用。我们需要计算出满足条件的不同方案的数量。

数据结构选择

为了高效地解决这个问题,我们可以使用动态规划(Dynamic Programming, DP)来存储中间状态。具体来说,我们可以使用一个字典 f 来记录当前的状态,其中键是一个元组 (a, b),表示已经使用了 a 个魔法棒,当前喜爱值之和为 b 的方案数。

算法步骤

  1. 预处理阶乘值

    • 由于我们需要计算喜爱值的阶乘,因此可以预先计算出所有可能的阶乘值,并存储在一个数组 magic 中。
  2. 初始化状态

    • 初始状态 f[(0, 0)] 表示没有使用任何魔法棒,喜爱值之和为 0 的方案数为 1。
  3. 动态规划更新状态

    • 对于每个甜点,我们有两个选择:
      1. 不使用魔法棒,直接将甜点的喜爱值加入当前的喜爱值之和。
      2. 使用魔法棒,将甜点的喜爱值变为其阶乘,并加入当前的喜爱值之和。
    • 我们需要遍历所有甜点,并更新状态 f
  4. 统计结果

    • 最终,我们需要统计所有满足条件的方案数,即喜爱值之和为 S 的所有状态。

代码详解

from collections import defaultdict

# 计算阶乘的魔法数组
magic = [1] * 100

def pre():
    for i in range(1, 100):
        magic[i] = magic[i - 1] * i

def solution(n, m, s, like):
    pre()
    f = defaultdict(int)  # 使用defaultdict来初始化map
    f[(0, 0)] = 1  # 初始状态

    for i in range(1, n + 1):
        g = f.copy()  # 备份当前的状态
        for (a, b), v in g.items():
            if b + like[i - 1] <= s:  # 加入"喜欢"的数量
                f[(a, b + like[i - 1])] += v
            if a + 1 <= m and b + magic[like[i - 1]] <= s:  # 加入"喜欢的阶乘"
                f[(a + 1, b + magic[like[i - 1]])] += v

    sum_ = 0
    for i in range(m + 1):
        sum_ += f[(i, s)]  # 累加满足条件的结果
    
    return sum_

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution(3, 2, 6, [1,2,3]) == 5 )
    print(solution(3, 1, 1, [1,1,1]) == 6 )
  • 预处理阶乘值

    • magic 数组用于存储从 1 到 99 的阶乘值。
    • pre() 函数用于预先计算这些阶乘值。
  • 初始化状态

    • f[(0, 0)] = 1 表示初始状态下没有使用任何魔法棒,喜爱值之和为 0 的方案数为 1。
  • 动态规划更新状态

    • 对于每个甜点 i,我们遍历当前的所有状态 (a, b),并更新两种可能的状态:
      1. 不使用魔法棒,直接将甜点的喜爱值加入当前的喜爱值之和。
      2. 使用魔法棒,将甜点的喜爱值变为其阶乘,并加入当前的喜爱值之和。
  • 统计结果

    • 最终,我们遍历所有可能的魔法棒使用次数 i,累加满足条件的状态 f[(i, s)],得到最终的方案数。

测试样例分析

  1. 样例1

    • 输入:n = 3, m = 2, s = 6, like = [1, 2, 3]
    • 输出:5
    • 解释:有 5 种不同的方案使得喜爱值之和为 6。
  2. 样例2

    • 输入:n = 3, m = 1, s = 1, like = [1, 1, 1]
    • 输出:6
    • 解释:有 6 种不同的方案使得喜爱值之和为 1。
  3. 样例3

    • 输入:n = 5, m = 3, s = 24, like = [1, 2, 3, 4, 5]
    • 输出:1
    • 解释:只有一种方案使得喜爱值之和为 24。
  4. 样例4

    • 输入:n = 4, m = 0, s = 10, like = [1, 3, 3, 3]
    • 输出:1
    • 解释:只有一种方案使得喜爱值之和为 10。
  5. 样例5

    • 输入:n = 6, m = 1, s = 35, like = [5, 5, 5, 5, 5, 5]
    • 输出:0
    • 解释:没有方案使得喜爱值之和为 35。

总结

本题通过动态规划的方法,有效地解决了在有限魔法棒使用次数下,选择甜点并可能使用魔法棒,使得喜爱值之和恰好等于预期值的问题。动态规划的状态转移方程清晰地描述了每一步的选择,并且通过预处理阶乘值,减少了重复计算,提高了算法的效率。