编号32题解 | 豆包MarsCode AI 刷题

28 阅读5分钟

题目

小F面临一个有趣的挑战:给定一个数组,她需要将数组中的数字分为两组。分组的目标是使得一组数字的和的个位数等于给定的 A,另一组数字的和的个位数等于给定的 B。除此之外,还有一种特殊情况允许其中一组为空,但剩余数字和的个位数必须等于 AB。小F需要计算所有可能的划分方式。

描述

给定一个整数数组 array_a 和两个整数 AB,计算所有可能的划分方式,使得一组数字的和的个位数等于 A,另一组数字的和的个位数等于 B。允许其中一组为空,但剩余数字和的个位数必须等于 AB

解题思路

  1. 预处理数组

    • 将数组中的每个元素取模 10,因为只关心个位数。
  2. 特殊情况处理

    • 计算数组的总和的个位数 total_sum
    • 如果 total_sum 等于 A 或 B,则直接返回 1,因为可以将所有数字放在一组,另一组为空。
  3. 动态规划

    • 使用二维数组 f,其中 f[i][j] 表示前 i 个元素中,一组和的个位数为 j 的划分方式数。

    • 初始化 f[0][0] = 1,表示没有任何元素时,和为 0 的划分方式数为 1。

    • 遍历数组,更新 f 数组:

      • 对于每个元素 array_a[i-1],可以选择将其放入当前组或另一组。
      • 更新 f[i][j] 为 f[i-1][j] 加上 f[i-1][(j - array_a[i-1] + 10) % 10]
  4. 返回结果

    • 返回 f[n][B],即前 n 个元素中,一组和的个位数为 B 的划分方式数。

代码详解

预处理数组
def solution(n, A, B, array_a):
    array_a = [x % 10 for x in array_a]
  • 取模操作

    • 将数组中的每个元素取模 10,只保留个位数。
特殊情况处理
    total_sum = sum(array_a)
    total_sum %= 10
    if (total_sum == A or total_sum == B):
        return 1
    if (total_sum != (A + B) % 10):
        return 0
  • 计算总和的个位数

    • 计算数组的总和 total_sum 并取模 10。
  • 特殊情况处理

    • 如果 total_sum 等于 A 或 B,直接返回 1。
    • 如果 total_sum 不等于 (A + B) % 10,直接返回 0。
动态规划
    f = [[0 for _ in range(10)] for _ in range(n + 1)]
    f[0][0] = 1
    for i in range(1, n + 1):
        for j in range(10):
            f[i][j] += f[i - 1][j]
            f[i][j] += f[i - 1][(j - array_a[i - 1] + 10) % 10]
  • 初始化

    • f[0][0] = 1,表示没有任何元素时,和为 0 的划分方式数为 1。
  • 动态规划更新

    • 遍历数组,更新 f 数组。
    • 对于每个元素 array_a[i-1],可以选择将其放入当前组或另一组。
    • 更新 f[i][j] 为 f[i-1][j] 加上 f[i-1][(j - array_a[i-1] + 10) % 10]
返回结果
    return f[n][B]

返回 f[n][B],即前 n 个元素中,一组和的个位数为 B 的划分方式数。

测试用例解析

测试用例1

输入n = 3, A = 1, B = 2, array_a = [1, 1, 1]

预处理数组

array_a = [x % 10 for x in array_a]
  • 将数组中的每个元素取模 10,只保留个位数。
  • 结果:array_a = [1, 1, 1]

特殊情况处理

total_sum = sum(array_a)
total_sum %= 10
if (total_sum == A or total_sum == B):
    return 1
if (total_sum != (A + B) % 10):
    return 0
  • 计算数组的总和 total_sum 并取模 10。

    • total_sum = 1 + 1 + 1 = 3
    • total_sum % 10 = 3
  • 检查特殊情况:

    • total_sum == 3,既不等于 A = 1,也不等于 B = 2
    • total_sum % 10 != (A + B) % 10,即 3 != (1 + 2) % 10
  • 不满足特殊情况,继续进行动态规划。

动态规划

f = [[0 for _ in range(10)] for _ in range(n + 1)]
f[0][0] = 1
for i in range(1, n + 1):
    for j in range(10):
        f[i][j] += f[i - 1][j]
        f[i][j] += f[i - 1][(j - array_a[i - 1] + 10) % 10]
初始化
  • f 是一个二维数组,f[i][j] 表示前 i 个元素中,一组和的个位数为 j 的划分方式数。
  • 初始化 f[0][0] = 1,表示没有任何元素时,和为 0 的划分方式数为 1。
动态规划过程
  1. 第1个元素

    • i = 1array_a[0] = 1

    • 对于 j 从 0 到 9:

      • f[1][0] = f[0][0] + f[0][(0 - 1 + 10) % 10] = 1 + 0 = 1
      • f[1][1] = f[0][1] + f[0][(1 - 1 + 10) % 10] = 0 + 1 = 1
      • f[1][2] = f[0][2] + f[0][(2 - 1 + 10) % 10] = 0 + 0 = 0
      • f[1][3] = f[0][3] + f[0][(3 - 1 + 10) % 10] = 0 + 0 = 0
      • f[1][4] = f[0][4] + f[0][(4 - 1 + 10) % 10] = 0 + 0 = 0
      • f[1][5] = f[0][5] + f[0][(5 - 1 + 10) % 10] = 0 + 0 = 0
      • f[1][6] = f[0][6] + f[0][(6 - 1 + 10) % 10] = 0 + 0 = 0
      • f[1][7] = f[0][7] + f[0][(7 - 1 + 10) % 10] = 0 + 0 = 0
      • f[1][8] = f[0][8] + f[0][(8 - 1 + 10) % 10] = 0 + 0 = 0
      • f[1][9] = f[0][9] + f[0][(9 - 1 + 10) % 10] = 0 + 0 = 0
    • 结果:f[1] = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0]

  2. 第2个元素

    • i = 2array_a[1] = 1

    • 对于 j 从 0 到 9

    • 结果:f[2] = [2, 2, 0, 0, 0, 0, 0, 0, 0, 0]

  3. 第3个元素

    • i = 3array_a[2] = 1

    • 对于 j 从 0 到 9

    • 结果:f[3] = [4, 4, 0, 0, 0, 0, 0, 0, 0, 0]

返回结果

return f[n][B]
  • 返回 f[3][2],即前 3 个元素中,一组和的个位数为 2 的划分方式数。
  • 结果:f[3][2] = 3

详细解释

  • 初始状态

    • f[0][0] = 1,表示没有任何元素时,和为 0 的划分方式数为 1。
  • 第一个元素

    • f[1][0] = 1:不选第一个元素,和为 0。
    • f[1][1] = 1:选第一个元素,和为 1。
  • 第二个元素

    • f[2][0] = 2:不选第二个元素,和为 0;选第二个元素,和为 1。
    • f[2][1] = 2:不选第二个元素,和为 1;选第二个元素,和为 2。
  • 第三个元素

    • f[3][0] = 4:不选第三个元素,和为 0;选第三个元素,和为 1。
    • f[3][1] = 4:不选第三个元素,和为 1;选第三个元素,和为 2。
    • f[3][2] = 3:不选第三个元素,和为 2;选第三个元素,和为 3。