【题解】数字魔法的加一操作 | 豆包MarsCode AI刷题

60 阅读3分钟

问题描述

数字魔法师小U发现了一种特殊的数字变换魔法。这个魔法可以对一个数字字符串进行"进位"操作。每次操作规则如下:

  • 对字符串中的每个数字进行加一操作
  • 当某位数字为9时,加一后变成 0,并在前面补 1

例如:

  • "798" 经过一次操作变成 "8109"(7→8, 9→0并向前增加一个1, 8→9)
  • "999" 经过一次操作变成 "101010"

现在给定一个数字字符串 num_str(长度为n)和操作次数 k,请计算经过 k 次操作后得到的最终结果。由于结果可能非常大,请将答案对 1000000007 (10^9 + 7) 取模。

输入

  • 第一行包含两个整数 nnkk1n501 \leq n \leq 50, 1k1001 \leq k \leq 100
  • 第二行包含一个长度为n的数字字符串 \text{num_str},仅由数字0-9组成

返回

  • 返回一个整数,表示最终结果对 1000000007 取模后的值

问题分析

读题时

这道题涉及字符串与数字的变换操作,通过模拟一个特定的“进位”规则对数字字符串进行多次操作。由于字符串长度和操作次数较短(最多 50 和 100),可以直接模拟解决。但经过多次操作后字符串长度可能增长得非常快,因此如何有效处理超长数字的存储和运算是解题的关键。

解题时

模拟进位规则

根据题目描述,每次操作的规则如下:

  1. 遍历字符串中的每个数字,将其加 1。
  2. 如果某位数字为 9,则加 1 后变成 0,并向前补一个 1。

这种规则进位会导致数字长度增加。例如:

  • 输入 798,经过一次操作后变成 8109
  • 输入 999,经过一次操作后变成 101010

多次操作

给定一个初始字符串和操作次数 kk,需要将操作重复执行 kk 次。由于每次操作都会增长字符串长度,直接存储和处理完整的结果可能不现实。不过题目要求将最终结果对 109+710^9 + 7 取模,因此可以通过以下技巧优化:

  1. 模拟操作时,将数字存储在双端队列(deque)中,以便高效处理插入和删除操作。
  2. 在模拟完成后,通过逐位构造结果数字,同时对 109+710^9 + 7 取模。

这种方式避免了超长字符串的直接存储。

代码分析与注释

from collections import deque
MOD = 1000000007
def solution(n, k, numStr):
    num_deq = deque(int(numStr[i]) for i in range(n))
    for _ in range(k):
        for i in range(len(num_deq)):
            num = num_deq.popleft()
            num += 1
            if num == 10:
                num_deq.append(1)
                num_deq.append(0)
            else:
                num_deq.append(num)
                
    result = 0
    for i in range(len(num_deq)):
        result = (result * 10 + num_deq.popleft()) % MOD
    return result

复杂度分析

时间复杂度 :每次操作需要遍历当前数字的长度 LL,最多执行 kk 次操作,因此复杂度为 O(k×L)O(k \times L)。由于数字长度会增长,理论上最坏情况下 LL 可达到 O(10k)O(10k)。构造最终结果的复杂度为 O(L)O(L)

空间复杂度 :由于使用双端队列存储数字,空间复杂度与数字长度 LL 成正比,为 O(L)O(L)

总结

这道题通过一个特定的进位规则考察了数字字符串的模拟和高效运算能力。核心在于:

  1. 理解并模拟操作规则。
  2. 通过双端队列处理动态增长的数字序列。