数字分组选择和为偶数方法计数

5 阅读4分钟

问题描述

小M面对一组从 1 到 9 的数字,这些数字被分成多个小组,并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。 numbers: 一个由多个整数字符串组成的列表,每个字符串可以视为一个数字组。小M需要从每个数字组中选择一个数字。 例如对于[123, 456, 789],14个符合条件的数为:147 149 158 167 169 248 257 259 268 347 349 358 367 369。 测试样例 样例1: 输入:numbers = [123, 456, 789] 输出:14 样例2: 输入:numbers = [123456789] 输出:4 样例3: 输入:numbers = [14329, 7568] 输出:10

问题理解

首先,我们需要明确问题的具体要求:

  1. 输入:一个由多个数字字符串组成的列表,例如 [123, 456, 789]。每个字符串代表一个数字组,小M需要从每个数字组中选择一个数字。
  2. 目标:组成一个新的数,使得这个数的各位数字之和为偶数。
  3. 输出:满足条件的不同分组和选择方法的总数。

示例分析

让我们通过提供的样例来更好地理解问题。

样例1

  • 输入:numbers = [123, 456, 789]
  • 输出:14

样例2

  • 输入:numbers = [123456789]
  • 输出:4

样例3

  • 输入:numbers = [14329, 7568]
  • 输出:10

解题思路

为了计算满足条件的选择方法总数,我们可以采用以下步骤:

  1. 统计每个数字组中奇数和偶数的数量

    • 对于每个数字组,统计其中奇数和偶数的个数。
    • 例如,对于数字组 123,奇数为 1 和 3,偶数为 2
  2. 动态规划

    • 使用动态规划来记录在选择到第 i 个数字组时,当前数字和的奇偶性。
    • 定义 dp[i][j],其中 i 表示第 i 个数字组,j 表示当前数字和的奇偶性(0 表示偶数,1 表示奇数)。
    • 初始状态:dp[0][0] = 1,表示在选择第 0 个数字组之前,数字和为偶数的方案数为 1
  3. 状态转移

    • 对于每个数字组,更新 dp 表:

      • 如果选择偶数,则当前数字和的奇偶性不变。
      • 如果选择奇数,则当前数字和的奇偶性翻转。
    • 具体来说,对于第 i 个数字组,假设其中有 even[i] 个偶数和 odd[i] 个奇数:

      • dp[i][0] = dp[i-1][0] * even[i] + dp[i-1][1] * odd[i]
      • dp[i][1] = dp[i-1][1] * even[i] + dp[i-1][0] * odd[i]
  4. 最终结果

    • 最终,dp[n][0] 即为满足条件的选择方法总数,其中 n 是数字组的数量。

具体实现

让我们以样例1为例,具体实现上述思路。

样例1numbers = [123, 456, 789]

  1. 统计每个数字组中奇数和偶数的数量

    • 数字组 123

      • 奇数:13 → 2 个
      • 偶数:2 → 1 个
    • 数字组 456

      • 奇数:5 → 1 个
      • 偶数:46 → 2 个
    • 数字组 789

      • 奇数:79 → 2 个
      • 偶数:8 → 1 个
  2. 初始化 dp 表

    • dp[0][0] = 1
    • dp[0][1] = 0
  3. 状态转移

    • 对于数字组 123

      • dp[1][0] = dp[0][0] * 1 + dp[0][1] * 2 = 1 * 1 + 0 * 2 = 1
      • dp[1][1] = dp[0][1] * 1 + dp[0][0] * 2 = 0 * 1 + 1 * 2 = 2
    • 对于数字组 456

      • dp[2][0] = dp[1][0] * 2 + dp[1][1] * 1 = 1 * 2 + 2 * 1 = 4
      • dp[2][1] = dp[1][1] * 2 + dp[1][0] * 1 = 2 * 2 + 1 * 1 = 5
    • 对于数字组 789

      • dp[3][0] = dp[2][0] * 1 + dp[2][1] * 2 = 4 * 1 + 5 * 2 = 14
      • dp[3][1] = dp[2][1] * 1 + dp[2][0] * 2 = 5 * 1 + 4 * 2 = 13
  4. 最终结果

    • dp[3][0] = 14,即满足条件的选择方法总数为 14

代码实现

以下是基于上述思路的 Python 代码实现:

python

复制

def count_even_sum_numbers(numbers):
    # 初始化 dp 表
    dp = [[0] * 2 for _ in range(len(numbers) + 1)]
    dp[0][0] = 1

    for i in range(1, len(numbers) + 1):
        num_str = numbers[i - 1]
        even_count = 0
        odd_count = 0
        for ch in num_str:
            digit = int(ch)
            if digit % 2 == 0:
                even_count += 1
            else:
                odd_count += 1
        # 更新 dp[i][0] 和 dp[i][1]
        dp[i][0] = dp[i - 1][0] * even_count + dp[i - 1][1] * odd_count
        dp[i][1] = dp[i - 1][1] * even_count + dp[i - 1][0] * odd_count

    return dp[len(numbers)][0]

# 测试样例
print(count_even_sum_numbers(["123", "456", "789"]))  # 输出:14
print(count_even_sum_numbers(["123456789"]))          # 输出:4
print(count_even_sum_numbers(["14329", "7568"]))     # 输出:10

复杂度分析

  • 时间复杂度O(n * m),其中 n 是数字组的数量,m 是每个数字组的平均长度。
  • 空间复杂度O(n),用于存储 dp 表。