卡牌翻面求和问题 | 豆包MarsCode AI刷题

87 阅读2分钟

卡牌翻面求和问题,问题描述 小M有n张卡牌,每张卡牌的正反面分别写着不同的数字,正面是a,背面是b,小M希望通过选择每张卡牌的一面,使得所有向上的数字之和可以被3整除。你需要告诉小M,一共有多少种不同的方案可以满足这个条件。由于可能的方案数量过大,结果需要对10的9次方+7取模。

例如,如果有3张卡牌,正反面数字分别为(1,2),(2,3)和(3,2),你需要找到所有满足这3张卡牌正面或背面朝上的数字之和可以被3整除的组合数。

测试样例 样例一: 输入:n=3,a=[1,2,3],b=[2,3,2] 输出:3 样例二: 输入:n=4,a=[3,1,2,4],b=[1,2,3,1] 输出:6 样例三: 输入:n =5,a=[1,2,3,4,5],b=[1,2,3,4,5] 输出:32

解题思路

  1. 理解问题:我们需要选择每张卡牌的一面,使得所有向上的数字之和可以被3整除。
  2. 状态定义:我们可以定义 dp[i][j] 表示前 i 张卡牌,使得数字之和模3余 j 的方案数。
  3. 状态转移
    • 对于每张卡牌,我们可以选择正面或背面。
    • 更新 dp[i][j] 时,考虑选择正面或背面的影响。
  4. 初始状态dp[0][0] = 1,表示没有卡牌时,和为0的方案数为1。
  5. 最终结果dp[n][0] 即为所求的方案数。

代码提示

以下是代码的框架,其中关键步骤用注释标出:

def solution(n: int, a: list, b: list) -> int:
    MOD = 10**9 + 7
    
    # 初始化dp数组,dp[i][j]表示前i张卡牌,使得数字之和模3余j的方案数
    dp = [[0] * 3 for _ in range(n + 1)]
    
    # 初始状态
    dp[0][0] = 1
    
    # 遍历每一张卡牌
    for i in range(1, n + 1):
        # 当前卡牌的正面和背面数字
        front = a[i - 1]
        back = b[i - 1]
        
        # 遍历所有可能的余数
        for j in range(3):
            # 选择正面的情况
            dp[i][(j + front) % 3] = (dp[i][(j + front) % 3] + dp[i - 1][j]) % MOD
            
            # 选择背面的情况
            dp[i][(j + back) % 3] = (dp[i][(j + back) % 3] + dp[i - 1][j]) % MOD
    
    # 最终结果
    return dp[n][0]

if __name__ == '__main__':
    print(solution(n = 3, a = [1, 2, 3], b = [2, 3, 2]) == 3)
    print(solution(n = 4, a = [3, 1, 2, 4], b = [1, 2, 3, 1]) == 6)
    print(solution(n = 5, a = [1, 2, 3, 4, 5], b = [1, 2, 3, 4, 5]) == 32)

关键步骤解释

  1. 初始化 dp 数组dp[i][j] 表示前 i 张卡牌,使得数字之和模3余 j 的方案数。
  2. 状态转移:对于每张卡牌,更新 dp 数组时,考虑选择正面或背面的影响。
  3. 最终结果dp[n][0] 即为所求的方案数。

你可以根据这个框架继续完善代码,确保每一步都正确实现。