进阶 · 累积

阶乘

读 N,输出 N! = 1 × 2 × … × N。和1 到 N 求和同一个累加器骨架 — 只是改成了乘法,而且藏着一堵你会用有趣方式撞上的墙。

一句话答案用 long long 把 1 到 N 累乘 —— 12! = 479001600 是最后一个能装进 32 位 int 的阶乘,而 0! 等于 1,不是 0。

题目

输入: 一个整数 N(0 ≤ N ≤ 12)。

输出: N!。

样例:

输入输出
5120
01

为什么上限是 12?因为 12! = 479,001,600 装得进 32 位 int — 13! 装不下。这个限制本身就是课程。

你的解答

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

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

卡住了?提示

提示 1 — 从 1 开始,不是 0

累加器从 1 开始(乘 0 会清空一切 — 这个"中性值"叫单位元)。然后 for (int i = 1; i <= n; i++) r *= i;。

提示 2 — N = 0 这个边界

按定义 0! = 1。上面的循环在 N = 0 时跑零圈,累加器保持 1 — 答案免费掉出来。当边界情况不需要额外代码时,说明你的结构对了。

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

int main() {
    int n;
    cin >> n;
    int r = 1;
    for (int i = 1; i <= n; i++) {
        r *= i;
    }
    cout << r << endl;
    return 0;
}

溢出悬崖:12! = 479,001,600 装得进 int(上限约 21 亿);13! 会静悄悄绕回成垃圾值 — 不报错,只是错数。更大的阶乘在真电脑上要用 long long(到 20!)或大整数技术。溢出也是为什么类型与上限(英文)重要,而不只是语法。

深度解析

为什么这样做对

累加器换成累乘,同时第一次撞上「答案装不进你选的类型」。这题的主角变成了增长速率。

代价

O(n) 次乘法。13! = 6,227,020,800 就已经超过 32 位有符号 int。

常见错法

  • int 在 13! 处静默溢出——你拿到一个看起来很正常、实际错误的数,没有任何报错。
  • 累乘初值写成 0 而不是 1,所有答案都是 0。

下一步

增长快到算不动的序列:斐波那契。

记住这两句

  • 13! 溢出 int;21! 连 unsigned long long 都装不下。
  • 累乘初值 1,累加初值 0。
🐞 这段是错的 —— 点开,亲手让它挂一次

累乘初值写成 0,结果全变 0

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    long long f = 0;
    for (int i = 1; i <= n; i++) f *= i;
    cout << f << endl;
    return 0;
}