原始题目
以下代码的输出是什么?
#include <iostream>
using namespace std;
int main() {
int n = 27;
while (n != 1) {
if (n % 2 == 0) n /= 2;
else n = 3 * n + 1;
cout << n << " ";
}
return 0;
}
答案:打印 111 个数,从
82一直到1(末尾带空格,无换行)
这是著名的 3n+1 问题(Collatz 猜想)
- n 是偶数:
n /= 2 - n 是奇数:
n = 3n + 1 - 循环直到 n 变成 1
Collatz 猜想:任意正整数经过有限步都会回到 1。这个猜想至今无人证明,但计算机已经验证到 \(2^{68}\) 以上的所有数都成立。
序列忽上忽下、最后总会坠回 1,像冰雹在云层中上下翻滚,所以又叫冰雹数。
n = 27 是最经典的例子:只需 111 步,中途却冲到 9232 的峰值——27 也是「步数远超比它小的数」的著名反差代表。
轨迹图
蓝点 = 奇数步(3n+1 上升),绿点 = 偶数步(n/2 下降):
前几个数的手算模拟
27 → 82 → 41 → 124 → 62 → 31 → 94 → 47 → 142 → 71 → 214 ...
- 27 是奇数:27×3+1 = 82 ← 第一个输出
- 82 是偶数:82/2 = 41
- 41 是奇数:41×3+1 = 124
- 之后一路忽上忽下,第 77 步冲到峰值 9232,再一路跌回 1
三个隐藏考点
- 初始的 27 不会打印——
cout在n更新之后执行,第一个输出是 82。如果cout放在循环开头,才会先打 27。 - 无换行:每个数后面是空格,最后也不会输出
endl。 - 死循环风险:若初值
n = 0(或负数),n != 1永远为真——0 一直除 2 还是 0,程序永不停止。正整数没问题。
数据规模:27 的全过程峰值只有 9232,
int完全够用;但如果起始数更大,中途可能超过 \(2^{31}\),竞赛中稳妥起见用long long。
考点总结(CSP-J 初赛选择题)
- 认出 3n+1 / Collatz / 冰雹数 模型:偶数减半、奇数三倍加一。
- 注意
cout位置决定初始值是否被打印。 - 循环条件
n != 1对 0 和负数会死循环。 - 27 的步数是 111,峰值 9232——选择题若问「大约多少步」「最大值」,可直接选接近的量级。
思考题
把 n = 27 改成 n = 7,会打印多少个数?
答案
16 个:7 → 22 → 11 → 34 → 17 → 52 → 26 → 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1,打印的是从 22 到 1 共 16 个数。



