问题描述
数字魔法师小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 取模后的值
测试样例
样例1:
输入:
n = 3 ,k = 1 ,num_str = "798"
返回:8109
解释:798 经过一次操作变成 8109
样例2:
输入:
n = 3 ,k = 3 ,num_str = "798"
返回:103221
- 第一次操作:798 → 8109
- 第二次操作:8109 → 92110
- 第三次操作:92110 → 103221
样例3:
输入:
n = 4 ,k = 3 ,num_str = "7989"
返回:10322132代码解析与解答
代码解答
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
const int MOD = 1000000007;
int solution(int n, int k, string num_str) {
while (k > 0) {
string next_num = "";
// 将字符串中的每一位数字加1
for (char c : num_str) {
int digit = c - '0'; // 将字符转换为整数
next_num += to_string(digit + 1); // 加1后转回字符串并拼接
}
num_str = next_num; // 更新 num_str
k--;
}
// 将结果字符串转换为整数并取模
long long result = 0;
for (char c : num_str) {
result = (result * 10 + (c - '0')) % MOD;
}
return result;
}
int main() {
// 测试用例
cout << solution(3, 1, "798") << endl; // 输出 8109
cout << solution(3, 3, "798") << endl; // 输出 103221
cout << solution(4, 3, "7989") << endl; // 输出 10322132
return 0;
}
代码结构分析
-
常量定义:
const int MOD = 1000000007;- 由于结果可能很大,我们需要对 109+710^9+7 取模。
MOD是一个常用的大质数,用于防止整数溢出,尤其在涉及高精度计算时。
- 由于结果可能很大,我们需要对 109+710^9+7 取模。
-
主逻辑函数
solution:- 输入:数字字符串
num_str,长度n,操作次数k。 - 输出:经过
k次数字逐位加 1 操作后的结果,对 109+710^9+7 取模。
- 输入:数字字符串
-
操作实现:
-
逐位加 1:
for (char c : num_str) { int digit = c - '0'; // 将字符转换为整数 next_num += to_string(digit + 1); // 加1后转为字符串 }- 遍历字符串,将每个字符转换为整数,执行加 1 操作后,转回字符串并拼接到结果中。
-
更新结果字符串:
num_str = next_num;- 每次操作的结果更新为新的字符串,供下一轮使用。
-
-
结果取模:
-
将处理完成的字符串逐位转换为整数,同时逐步取模:
long long result = 0; for (char c : num_str) { result = (result * 10 + (c - '0')) % MOD; }- 这种方法避免了直接转换超大整数导致溢出问题。
-
-
主函数测试:
- 调用
solution函数,传入测试用例,并输出结果。
- 调用
代码的完整性与扩展性
-
处理多轮操作:
- 循环内的字符串逐位操作可扩展到任意次数,满足题目约束 k≤100k \leq 100。
-
大数处理能力:
- 字符串操作结合逐步取模的方法,能有效处理长达 50 位的数字。
运行示例
示例 1:
输入:solution(3, 1, "798")
输出:8109
过程:
- 第 1 次操作:
798→8109 - 最终结果对 109+710^9+7 取模:
8109 % 1000000007 = 8109
示例 2:
输入:solution(3, 3, "798")
输出:103221
过程:
- 第 1 次操作:
798→8109 - 第 2 次操作:
8109→92110 - 第 3 次操作:
92110→103221 - 最终结果对 109+710^9+7 取模:
103221 % 1000000007 = 103221
示例 3:
输入:solution(4, 3, "7989")
输出:10322132
过程:
- 第 1 次操作:
7989→810910 - 第 2 次操作:
810910→9211011 - 第 3 次操作:
9211011→10322132 - 最终结果对 109+710^9+7 取模:
10322132 % 1000000007 = 10322132
总结与扩展
总结
-
功能清晰:
- 实现了逐位加 1 的数字字符串操作,符合问题要求。
-
关键技术点:
- 字符串处理:将字符串当作大数存储,并模拟数字加法。
- 高效取模:通过逐位累积的方法避免直接处理超大整数。
-
复杂度分析:
- 时间复杂度:每次操作 O(n)O(n),共 kk 次,总复杂度为 O(kn)O(kn),其中 nn 是字符串长度。
- 空间复杂度:存储结果字符串和中间变量,复杂度为 O(n)O(n)。
生活中的应用场景
-
大整数计算:
- 在密码学中,大整数的处理(如 RSA 加密)常常需要字符串模拟加法和取模操作。
-
循环计数:
- 模拟计数器的进位(如机械里程表或电子设备计数器),逻辑类似本题逐位加法。
-
金融与物流:
- 处理长数字(如订单号、银行账户)的逐步操作,可用于订单系统、编号生成等场景。