小u的问好替换问题-MarsCode AI 刷题

74 阅读4分钟

问题描述

小C拿到了一个由数字字符和 ? 组成的字符串,她的目标是将所有的 ? 替换成数字字符,使得替换后的字符串表示的十进制整数成为正整数 pp 的倍数。由于方案数可能非常大,需要对最终的结果取模 109+7109+7。


测试样例

样例1:

输入:s = "??",p = 1
输出:100

样例2:

输入:s = "????1",p = 12
输出:0

样例3:

输入:s = "1??2",p = 3
输出:34

问题理解

你有一个由数字字符和 ? 组成的字符串 s,目标是将其中的所有 ? 替换成数字字符,使得替换后的字符串表示的十进制整数是给定正整数 p 的倍数。由于可能的替换方案数可能非常大,最终结果需要对 10^9 + 7 取模。

数据结构选择

  1. 字符串处理:由于我们需要替换字符串中的 ?,字符串处理是不可避免的。
  2. 动态规划(DP) :考虑到可能的替换方案数非常大,使用动态规划来记录不同状态下的有效方案数是一个不错的选择。

算法步骤

  1. 初始化:定义一个动态规划数组 dp,其中 dp[i][r] 表示前 i 个字符组成的字符串,其对 p 取模的余数为 r 的方案数。

  2. 状态转移

    • 如果当前字符是数字,直接更新 dp 数组。
    • 如果当前字符是 ?,则需要考虑所有可能的数字(0-9),并更新 dp 数组。
  3. 取模操作:在每次更新 dp 数组时,都需要对 10^9 + 7 取模,以防止数值溢出。

  4. 最终结果:最终结果是 dp[len(s)][0],即整个字符串对 p 取模为 0 的方案数。

总结

通过动态规划,我们可以有效地计算出所有可能的替换方案数,并确保结果在合理范围内。

    MOD = 10**9 + 7
    n = len(s)
    
    # 初始化 dp 数组
    dp = [[0] * p for _ in range(n + 1)]
    dp[0][0] = 1  # 空字符串对任何数取模都是 0
    
    # 遍历字符串 s
    for i in range(1, n + 1):
        for r in range(p):
            if s[i - 1] == '?':
                # 如果是 '?',考虑所有可能的数字
                for digit in range(10):
                    new_r = (r * 10 + digit) % p
                    dp[i][new_r] = (dp[i][new_r] + dp[i - 1][r]) % MOD
            else:
                # 如果是数字,直接更新
                digit = int(s[i - 1])
                new_r = (r * 10 + digit) % p
                dp[i][new_r] = (dp[i][new_r] + dp[i - 1][r]) % MOD
    
    # 最终结果是 dp[n][0]
    return dp[n][0]

if __name__ == '__main__':
    print(solution("??", 1) == 100)
    print(solution("????1", 12) == 0)
    print(solution("1??2", 3) == 34)
  1. 初始化

    • 我们初始化了一个二维数组 dp,其中 dp[i][r] 代表在考虑前 i 个字符时,模 p 的结果为 r 的方式数目。
    • 初始状态 dp[0][0] = 1,表示空字符串的模数是 0。
  2. 状态转移

    • 对于每个字符 s[i-1],我们需要根据其值(数字或 '?')来更新 dp 数组:

      • 如果是数字,直接用该数字更新当前模数。
      • 如果是 '?',则尝试用 0 到 9 中的每个数字更新模数。
  3. 最终输出

    • 最终的答案是 dp[n][0],即考虑所有字符后,模 p 为 0 的方式数。

实验结果

  1. 测试用例 1

    • 输入:s = "??", p = 1
    • 解释:所有的两位数 ?? 都能被替换成从 00 到 99 的数字,而每个数字对 1 取模的结果总是 0。因此,输出应为 100。
    • 输出:100,与预期一致。
  2. 测试用例 2

    • 输入:s = "????1", p = 12
    • 解释:任何替换字符后,最后的数字模 12 都不可能等于 0,因此输出应为 0。
    • 输出:0,与预期一致。
  3. 测试用例 3

    • 输入:s = "1??2", p = 3
    • 解释:通过替换问号,考虑所有可能的数字,最终得到对 3 取模为 0 的数字的个数。结果为 34。
    • 输出:34,与预期一致。

实验总结

  • 动态规划 是解决此类问题的关键,能够有效地管理和更新状态,避免了暴力穷举的高时间复杂度。
  • 边界条件 处理得当,特别是空字符串的模数。
  • 时间复杂度O(n * p * 10),其中 n 是字符串的长度,p 是模数,10是因为每个 '?' 可能替换成 0 到 9 之间的任意一个数字。