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

22 阅读3分钟
  • 题目解析

题目原题:小M有 n 张卡牌,每张卡牌的正反面分别写着不同的数字,正面是 a,背面是 b。小M希望通过选择每张卡牌的一面,使得所有向上的数字之和可以被3整除。计算一共有多少种不同的方案可以满足这个条件。

  • 思路:通过一组二位数组来存放前 i 张卡牌中,选择某些卡牌使得和模3余 j 的方案。对于每张卡牌,我们有两种选择:选择正面或选择背面,这将导致新的模3状态。我更新二位数组来展示新的状态,并遍历计算每个卡牌(包括正反面),检查数组中总和能被3整除的方案数。

因此,我们定义一个二维数组arr[i][j],其中i表示考虑到第i张卡牌,j表示前i张卡牌选择和模3的余数(0, 1, 2)。 arr[i][j]表示考虑到第i张卡牌时,选择和模3余j的方案数。

当前卡牌的正反面数字分别为a和b。如果选择正面,则前i张卡牌选择和的模3余数会从j变为(j + a % 3) % 3。 如果选择背面,则前i张卡牌选择和的模3余数会从j变为(j + b % 3) % 3。 因此,更新状态的计算方程为:arr[i][j] = arr[i-1][(j - a % 3 + 3) % 3] + arr[i-1][(j - b % 3 + 3) % 3]。

注意两点:由于模运算的结果可能为负数,所以使用(j - a % 3 + 3) % 3来确保结果是非负的。当没有卡牌时(即i = 0),和为0的方案数为1,因此arr[0][0] = 1,其他arr[0][j](j ≠ 0)均为0。

  • 解题步骤
  1. 初始化二维数组arr,设置arr[0][0] = 1,其他元素为0。
  2. 遍历每张卡牌,对于每张卡牌,根据其正反面数字a和b,更新数组。
  3. 遍历完成后,读取arr[n][0]的值,即为所求答案。
  • 示例

假设有3张卡牌,正反面数字分别为(1, 2),(2, 3)和(3, 2)。

初始化数组为:arr[0][0] = 1,arr[0][1] = 0,arr[0][2] = 0

遍历第一张卡牌(1, 2):

arr[1][0] = arr[0][(0 - 1 % 3 + 3) % 3] + arr[0][(0 - 2 % 3 + 3) % 3] = arr[0][2] + dp[0][1] = 0 + 0 = 0

arr[1][1] = arr[0][(1 - 1 % 3 + 3) % 3] + arr[0][(1 - 2 % 3 + 3) % 3] = arr[0][0] + dp[0][2] = 1 + 0 = 1

arr[1][2] = arr[0][(2 - 1 % 3 + 3) % 3] + arr[0][(2 - 2 % 3 + 3) % 3] = arr[0][1] + dp[0][0] = 0 + 1 = 1

  • 依此类推,遍历完所有卡牌后,得到最终的arr数组,并读取arr[3][0]的值作为答案。

通过这种方法,我们可以高效地计算出满足条件的所有不同选择方案的数量。

遍历完所有卡牌后,最终答案为 arr[n][0],表示前 n 张卡牌中,选择某些卡牌使得和模3余0的方案数。