专栏文章

B4344 [语言月赛 202506] 数字转转转 题解

B4344题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mip2hyjz
此快照首次捕获于
2025/12/03 05:05
3 个月前
此快照最后确认于
2025/12/03 05:05
3 个月前
查看原文

Source & Knowledge

2025 年 6 月语言月赛,由洛谷网校入门计划/基础计划提供。

题目大意

给定一个正整数 xx,定义一次“数字转转转”操作为将其每一位数字相加得到一个新数。例如,375375 经过一次操作变为 3+7+5=153 + 7 + 5 = 15,再次操作变为 1+5=61 + 5 = 6。现在,对于 11nn 的每个数字 ii,需要对其进行 aia_i 次“数字转转转”操作,并输出最终的结果。

题目分析

对于每个数字 ii(从 11nn),我们将其作为初始值 xx。然后,循环 aia_i 次。在一个内部循环中,计算 xx 的各位数字之和,并将结果赋值回 xx
计算各位数字之和的方法:
CPP
int sum = 0;
while (num > 0) {
   sum += num % 10; // 取出个位数字
   num /= 10;       // 去掉个位数字
}
return sum;
将这个逻辑应用到题目中:
CPP
// 对于从1到n的每个数字i
for (int i = 1; i <= n; ++i) {
    int cnt; // 当前数字i需要进行的转转转次数
    cin >> cnt;

    int x = i; // 初始值为i
    // 进行转转转操作,最多cnt次,但只要x变为个位数就停止
    for (int j = 1; j <= cnt; ++j) {
        int sum = 0;
        // 计算x的各位数字之和
        while (x > 0) {
            sum += x % 10;
            x /= 10;
        }
        x = sum; // 更新x为各位数字之和
        if (x < 10) {    // 如果x已经是小于10的个位数,则后续操作结果不变
            break;       // 跳出内层循环
        }
    }
    cout << x << " "; // 输出最终结果
}
代码中有一个 if (x < 10) { break; },现对其作一个直观解释。
由于“数字转转转”操作的最终结果是一个个位数,并且一旦达到个位数,后续操作结果不变,这意味着我们不需要真正执行 aia_i 次操作。实际上,对于任何大于 99 的数,经过两三次操作通常就会变成小于 1010 的数。例如 999999+9+9+9+9=454+5=999999 \to 9+9+9+9+9 = 45 \to 4+5 = 9。即使 aia_i 非常大(例如 10910^9),我们也不需要循环 10910^9 次。我们只需要循环直到当前数字变为个位数即可。一旦变为个位数,就可以直接跳出循环,输出结果。
题目中的 aia_i 实际上只影响循环的上限,真正决定循环次数的是 x<10x < 10 的条件,次数可能远远达不到 aia_i。因为一旦 xx 变为个位数,它就不会再改变,所以即使 aia_i 很大,我们也不需要执行那么多次操作,很少次数(两三次)的操作即可。这正是代码中的 if (x < 10) break; 的作用。

评论

1 条评论,欢迎与作者交流。

正在加载评论...