问题描述
数字魔法师小U发现了一种特殊的数字变换魔法。这个魔法可以对一个数字字符串进行"进位"操作。每次操作规则如下:
- 对字符串中的每个数字进行加一操作
- 当某位数字为9时,加一后变成 0,并在前面补 1
例如:
- "798" 经过一次操作变成 "8109"(7→8, 9→0并向前增加一个1, 8→9)
- "999" 经过一次操作变成 "101010"
现在给定一个数字字符串 num_str(长度为n)和操作次数 k,请计算经过 k 次操作后得到的最终结果。由于结果可能非常大,请将答案对 1000000007 (10^9 + 7) 取模。
输入
- 第一行包含两个整数 n 和 k(1 ≤ n ≤ 50, 1 ≤ k ≤ 100)
- 第二行包含一个长度为n的数字字符串 num_str,仅由数字0-9组成
返回
- 返回一个整数,表示最终结果对 1000000007 取模后的值
测试样例
略
思路一
根据题目要求将加一和进位步骤分别看待: 为了实现这个功能,我们可以分两步来进行:
- 单次加一操作:设计一个函数来处理单次的加一操作,确保能够正确处理进位情况。
- 多次操作:根据给定的操作次数
k,重复调用单次加一操作的函数。
单次加一操作
对于单次加一操作,我们需要考虑以下几种情况:
- 如果当前位不是9,直接加一。
- 如果当前位是9,变为0,并产生一个进位。
- 遍历完所有位后,如果还有进位,需要在结果字符串的最前面添加1。
实现细节
我们可以从字符串的末尾开始遍历,这样更容易处理进位问题。具体步骤如下:
-
初始化一个空列表
result来存储结果字符串的每一位。 -
初始化一个变量
carry用于记录是否有进位。 -
从字符串的末尾开始遍历每一位数字:
- 将当前位数字加一,并加上进位
carry。 - 如果结果为10,将当前位设为0,并设置
carry为1。 - 否则,将当前位设为结果,并将
carry设为0。
- 将当前位数字加一,并加上进位
-
遍历结束后,如果
carry仍为1,需要在结果字符串的最前面添加1。 -
最后,将
result列表反转并拼接成最终的字符串。
多次操作
根据给定的操作次数 k,我们需要重复调用单次加一操作的函数。具体步骤如下:
- 初始化一个变量
num_str存储当前的数字字符串。 - 循环
k次,每次调用单次加一操作的函数,并更新num_str。
取模操作
题目要求最终结果对 109+7109+7 取模。因此,在所有操作完成后,我们需要将结果字符串转换为整数,并进行取模操作。
def solution(num_str, k):
MOD = 10**9 + 7
def add_one(s):
carry = 0
result = []
for digit in reversed(s):
new_digit = int(digit) + 1 + carry
if new_digit == 10:
result.append('0')
carry = 1
else:
result.append(str(new_digit))
carry = 0
if carry:
result.append('1')
return ''.join(reversed(result))
# 进行 k 次变换
for _ in range(k):
num_str = add_one(num_str)
# 将最终结果转换为整数并对 MOD 取模
final_result = int(num_str) % MOD
return final_result
思路二
注意到题目要求的操作与数字本身的加一操作一致,将字符串依次转换为数字后可使用加法运算直接得到结果。
def solution(n: int, k: int, num_str: str) -> int:
lis = []
for _ in range(k):
for i in num_str:
x = int(i)+1
lis.append(str(x))
res = ''.join(lis)
result = []
num_str = res
res = int(res)
res = res % 1000000007
return res