老题新解|求 10000 以内 n 的阶乘
《信息学奥赛一本通》第168题:求10000以内n的阶乘
求10,000以内n的阶乘。
输入:
只有一行输入,整数n(0<=n<=10,000)。
输出:
一行,即n!的值。
样例输入:
100
样例输出:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000
大家好,我是莫小特。
这篇文章给大家带来《信息学奥赛一本通》中的第 168 题:求 10000 以内 n 的阶乘。
一、题目描述
求10,000以内n的阶乘。
输入:
只有一行输入,整数n(0<=n<=10,000)。
输出:
一行,即n!的值。
样例输入:
100
样例输出:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000
二、题意分析
这道题是信息学奥赛一本通练习题的第 168 题。
输入格式为一行一个整数 n,使用 int 类型。
int n;
cin>>n;
对于小的 n(例如 n ≤ 20),直接用 long long 计算 n! 是没问题的,但当 n ≥ 21 时,阶乘的值就已经超过了 long long 的范围。
所以只能使用高精度算法才能实现。
我们知道:
n!=1×2×3×…×nn!=1×2×3×…×nn!=1×2×3×…×n
我们可以用一个数组 a[]
来保存每一位数字(倒序存储更方便计算),然后依次模拟手工乘法:
(1)初始化:a[1] = 1
,表示当前结果是 1。
a[1] = 1; // 初始结果为 1
(2)逐步相乘:依次乘以 2、3、4、…、n。
使用 for 循环实现。
for (int i = 1; i <= n; ++i) // 从 1 乘到 n
(3)模拟竖式乘法:
每次循环将 a[j]
乘以当前的 i,再加上上一位的进位,结果对 10 取模存回当前位,商部分作为下一位的进位。
x = 0; // 每次从无进位开始
for (int j = 1; j <= len; ++j)
{a[j] = a[j] * i + x; // 当前位乘 i 并加上进位x = a[j] / 10; // 计算新的进位a[j] %= 10; // 保留个位数字
}
(4)判断是否需要增加长度:如果进位使得新的一位非零,就增加 len
。
// 若乘完后还有进位,则继续加位
while (x > 0)
{a[++len] = x % 10;x /= 10;
}
(5)输出时倒序打印(因为低位存在前面)。
// 输出结果(倒序)
for (int i = len; i >= 1; --i)cout << a[i];
按照样例输入对数据进行验证。
符合样例输出结果。
三、完整代码
该题的完整代码如下:
#include <iostream>
#include <cstring>
using namespace std;int a[40010], n, x, len = 1;int main()
{cin >> n; // 输入 na[1] = 1; // 初始结果为 1for (int i = 1; i <= n; ++i) // 从 1 乘到 n{x = 0; // 每次从无进位开始for (int j = 1; j <= len; ++j){a[j] = a[j] * i + x; // 当前位乘 i 并加上进位x = a[j] / 10; // 计算新的进位a[j] %= 10; // 保留个位数字}// 若乘完后还有进位,则继续加位while (x > 0){a[++len] = x % 10;x /= 10;}}// 输出结果(倒序)for (int i = len; i >= 1; --i)cout << a[i];cout << endl;return 0;
}
四、总结
通过本题《求 10000 以内 n 的阶乘》的练习,我们掌握了高精度乘法的完整实现过程。
由于阶乘增长极快,即使是 n = 100
,结果也已经超过了所有基本整数类型的表示范围,因此需要使用数组模拟大整数运算。
在本题中,我们主要收获了以下几个知识点:
1、 高精度存储思想
使用数组 a[]
按位存储每一位数字(低位在前,高位在后),便于逐位计算和进位操作。
2、模拟竖式乘法运算
对每一位执行 a[j] = a[j] * i + x
,再用 /10
求进位、%10
保留个位,实现和手工乘法一致的逻辑。
3、动态控制数组长度
每次乘完后若有新的进位,则继续增加结果长度 len
,确保结果完整。
4、倒序输出结果
由于计算时是倒序存储的,输出时需从高位(len
)开始依次输出,才能得到正确的阶乘结果。
技巧总结:
高精度乘法是高精度运算的核心,思路与“2 的 N 次方”题相似,但乘数是递增变化的。
注意在每次乘法中清空进位变量 x
,否则会影响下一轮计算。
阶乘结果的位数非常多,要根据实际最大 n 值合理预留数组大小。
通过这道题,我们进一步掌握了高精度算法的通用框架,并为解决更复杂的大数加法、乘法、组合数等问题奠定了坚实的基础。
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注我哦!
如果有更好的方法也可以在评论区评论哦,我都会看哒~
我们下集见~