易–中 · 循环模拟

冰雹序列

偶数就砍一半,奇数就乘三加一。没人证明得了「是不是所有数最终都会到 1」—— 但你的循环能替你验算任何一个数。

一句话答案n 是偶数就除以 2、是奇数就变成 3n + 1,一直数到 n 等于 1 —— n = 1 本身要输出 0 步,这是最容易被忘掉的情况。

题目

输入: 一个整数 n(1 ≤ n ≤ 100000)。

输出: 到达 1 需要多少步。如果 n 本来就是 1,输出 0。

样例:

输入输出
68
10

以 6 为例:6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1。数箭头 —— 一共 8 个。到达 1 是终点,它本身不算一步。

你的解答

main.cpp — 你的解答
「运行我的输入」用的自定义输入

判题在浏览器本地运行。死循环会在 3 秒后被自动中断 —— 但还是确保每个循环都有出口。代码随打随存。

卡住了?提示

提示 1 — 规则是循环体,不是公式

这没有闭式解 —— 你算不出答案,只能走一遍。这就是 while 循环:不断变换 n,每变换一次计一步。

提示 2 — 奇偶各一个分支

n % 2 == 0 表示偶数 → n = n / 2。否则 → n = 3 * n + 1。这里整数除法正是你要的:既然已经确认是偶数,就不必担心余数。

提示 3 — 差一错误藏在循环条件里

用 while (n != 1),在循环体内自增。如果你把 steps 初始化成 1,或者在输出之后才自增,每个答案都会差一 —— 而且 n = 1 会输出 1 而不是 0。

题解(先自己试试!)
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int steps = 0;
    while (n != 1) {
        if (n % 2 == 0) n = n / 2;
        else n = 3 * n + 1;
        steps++;
    }
    cout << steps << endl;
    return 0;
}

这就是考拉兹猜想:从任何正整数出发,序列似乎总会到 1,但没人证明得了。你的程序是一次小小的数学实验 —— 试试 27,看它先爬到 9232 再一路落下。这种「把规则跑一遍,然后看数字」的习惯,正是面对没有公式的问题时建立直觉的方式。继续:数单词。

深度解析

为什么这样做对

这条规则没有公式,所以你算不出答案,只能一步步走。把规则写成循环体、把步数写成计数器 —— 这是所有模拟类问题的通用骨架。

代价

O(步数),而且没人能给出通用的上界 —— 这正是考拉兹猜想至今未解的原因。n ≤ 100000 时实测都在几百步以内。

常见错法

  • 把 steps 初始化成 1,或者在输出之后才自增,每个答案都差一 —— 而且 n = 1 会输出 1 而不是 0。
  • 把 n != 1 写成 n > 1:正数下看着等价,可一旦某次笔误让序列掉进负数,循环就再也停不下来了。

下一步

下一步,把「边扫边记状态」用到文本上:数单词。

记住这两句

  • 没有公式的规则,就写成循环体,让机器替你走。
  • 到达终点不算一步 —— 循环条件和计数器必须对齐。
🐞 这段是错的 —— 点开,亲手让它挂一次

steps 从 1 开始 —— 每个答案都多一

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int steps = 1;
    while (n != 1) {
        if (n % 2 == 0) n = n / 2;
        else n = 3 * n + 1;
        steps++;
    }
    cout << steps << endl;
    return 0;
}