进阶 · 累积
阶乘
读 N,输出 N! = 1 × 2 × … × N。和1 到 N 求和同一个累加器骨架 — 只是改成了乘法,而且藏着一堵你会用有趣方式撞上的墙。
一句话答案用 long long 把 1 到 N 累乘 —— 12! = 479001600 是最后一个能装进 32 位 int 的阶乘,而 0! 等于 1,不是 0。
题目
输入: 一个整数 N(0 ≤ N ≤ 12)。
输出: N!。
样例:
| 输入 | 输出 |
|---|---|
5 | 120 |
0 | 1 |
为什么上限是 12?因为 12! = 479,001,600 装得进 32 位 int — 13! 装不下。这个限制本身就是课程。
你的解答
「运行我的输入」用的自定义输入
判题在浏览器本地运行。死循环会在 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;
}