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

37 阅读3分钟

题解

这道题要求我们计算在给定的n张卡牌中,通过选择每张卡牌的一面(正面或背面),使得所有向上的数字之和可以被3整除的不同方案数。为了解决这个问题,我们可以使用动态规划的方法来追踪到目前为止的所有可能的和对3取模的结果。

动态规划状态定义

  • dp[i][j] 表示前i张卡牌中,选择某些卡牌使得这些卡牌上数字之和模3余j的方案数。
    • i 的范围是 [0, n],其中 n 是卡牌总数。
    • j 的范围是 [0, 2],表示当前累计和对3取模的结果。

状态转移

对于每一张卡牌,我们有两种选择:

  1. 选择这张卡牌的正面,此时新的累积和将是 (j + a[i-1]) % 3
  2. 选择这张卡牌的背面,此时新的累积和将是 (j + b[i-1]) % 3

基于上述两种选择,我们可以更新 dp[i][newSum1]dp[i][newSum2],其中 newSum1 = (j + a[i-1]) % 3newSum2 = (j + b[i-1]) % 3

初始条件

  • 当没有选择任何卡牌时,即 i=0 时,只有当和为0的情况有一种方案,因此 dp[0][0] = 1

最终结果

  • 我们需要找到所有n张卡牌中,总和模3余0的方案数,即 dp[n][0]

代码实现

public class Main {
    public static int solution(int n, int[] a, int[] b) {
        int MOD = 1000000007;
        // dp[i][j] 表示前 i 张卡牌中,选择某些卡牌使得和模3余 j 的方案数
        int[][] dp = new int[n + 1][3];
        
        // 初始化:前0张卡牌,和为0的方案数为1
        dp[0][0] = 1;
        
        // 遍历每一张卡牌
        for (int i = 1; i <= n; i++) {
            // 当前卡牌的正面和背面数字
            int front = a[i - 1];
            int back = b[i - 1];
            
            // 更新 dp 数组
            for (int j = 0; j < 3; j++) {
                // 选择正面的情况
                int newSum1 = (j + front) % 3;
                dp[i][newSum1] = (dp[i][newSum1] + dp[i - 1][j]) % MOD;
                
                // 选择背面的情况
                int newSum2 = (j + back) % 3;
                dp[i][newSum2] = (dp[i][newSum2] + dp[i - 1][j]) % MOD;
            }
        }
        
        // 最终答案是前 n 张卡牌中,和模3余0的方案数
        return dp[n][0];
    }

    public static void main(String[] args) {
        System.out.println(solution(3, new int[]{1, 2, 3}, new int[]{2, 3, 2}) == 3);
        System.out.println(solution(4, new int[]{3, 1, 2, 4}, new int[]{1, 2, 3, 1}) == 6);
        System.out.println(solution(5, new int[]{1, 2, 3, 4, 5}, new int[]{1, 2, 3, 4, 5}) == 32);
    }
}

感想总结

解决这类问题的关键在于理解如何将问题分解成更小的子问题,并利用动态规划来有效地存储中间结果,从而避免重复计算。本题中,通过对每张卡牌的两种选择进行状态转移,能够有效地计算出满足条件的方案数量。这种方法不仅适用于本题,也广泛应用于其他组合优化问题中。

此外,处理大数时,使用模运算可以有效防止数值溢出。在实际应用中,这种技巧对于确保程序的稳定性和正确性非常重要。通过练习这样的题目,可以增强对动态规划的理解,并提高解决复杂问题的能力。