角谷猜想

GitHub跳转原题关系图返回列表

按奇偶分支模拟角谷变换,每步输出算式,直到当前数变为 1。

OJ: roj

题目 ID: 1086

难度:入门

标签:

创建: 2026-09-29 18:05

更新: 2026-10-05 00:33

题目描述

对正整数 N (N⩽2 000 000)N\,(N\leqslant 2\,000\,000) 反复变换:奇数则乘 33 加 11,偶数则除以 22,直到得到 11。输出每步算式(每步一行),最后一行输出 End;若输入为 11 则直接输出 End。样例:输入 5,输出 5*3+1=16、16/2=8、8/2=4、4/2=2、2/2=1、End。

思路

直接模拟:维护当前值 nn,当 n≠1n\neq 1 时按奇偶性算出下一步并输出等式,最后输出 End。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-07-05 22:00
# update_at: 2026-10-04 13:07

import sys


def next_collatz(n: int) -> tuple[int, str]:
    """返回 n 的下一步结果与等式字符串。"""
    if n & 1:  # 奇数
        m = n * 3 + 1
        return m, f"{n}*3+1={m}"
    m = n >> 1  # 偶数除以 2
    return m, f"{n}/2={m}"


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    n = next(data, None)
    if n is None:  # 空输入直接结束
        return

    out: list[str] = []
    while n != 1:
        n, line = next_collatz(n)
        out.append(line)
    out.append("End")

    sys.stdout.write("\n".join(out))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 00:33
 * update_at: 2026-10-05 00:33
 */
// main.cpp:按角谷猜想规则反复变换 n,输出每一步算式,最后输出 End。
#include <iostream>

typedef long long ll;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    ll n; // 当前数值,角谷过程会把它放大,用 ll 更安全
    std::cin >> n;

    // n 为 1 时不进循环,直接输出 End
    while (n != 1) {
        if (n % 2 == 1) { // 奇数:变成 3n+1
            ll nxt = n * 3 + 1;
            std::cout << n << "*3+1=" << nxt << "\n";
            n = nxt;
        } else { // 偶数:变成 n/2
            ll nxt = n / 2;
            std::cout << n << "/2=" << nxt << "\n";
            n = nxt;
        }
    }
    std::cout << "End" << "\n";
    return 0;
}