题目描述
用高精度计算出 S=1!+2!+3!+⋯+n!S=1!+2!+3!+⋯+n!(n≤50n≤50)。
其中 !
表示阶乘,定义为 n!=n×(n−1)×(n−2)×⋯×1n!=n×(n−1)×(n−2)×⋯×1。例如,5!=5×4×3×2×1=1205!=5×4×3×2×1=120。
输入格式
一个正整数 nn。
输出格式
一个正整数 SS,表示计算结果。
输入输出样例
输入 #1
3
输出 #1
9
说明/提示
【数据范围】
对于 100%100% 的数据,1≤n≤501≤n≤50。
【其他说明】
注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 n≤20n≤20,使用书中的代码无法通过本题。
如果希望通过本题,请继续学习第八章高精度的知识。
NOIP1998 普及组 第二题
解题思路
首先,需要理解阶乘的概念。阶乘表示一个数从1乘到那个数的过程,例如5! = 5 × 4 × 3 × 2 × 1。
然后,要计算从1!到n!的总和,需要逐个计算每个阶乘的值,并将它们累加起来。
具体步骤如下:
- 初始化一个数组来存储最终结果,以及一个数组来存储临时计算的中间结果。
- 从1开始循环到n,对于每个数i,计算i!的值。
- 对于每个i,初始化一个数组来存储i!的值,并将该数组的第一个元素设置为1(因为任何数的0阶乘都是1)。
- 然后,从1循环到i,对于每个数j,将j与i!的当前值相乘,并将结果存储在临时数组中。注意,这里的乘法需要模拟手算乘法的过程,即逐位相乘并处理进位。
- 将临时数组中的值复制到i!的数组中,以便进行下一次迭代。
- 将i!的值加到最终结果的数组中。同样,这里的加法也需要模拟手算加法的过程,即逐位相加并处理进位。
- 循环结束后,最终结果数组中的值就是S的值。
最后,将最终结果数组转换为整数并输出。
代码
#include<stdio.h>
using namespace std;
int main() //
{
int i, A[1005] = {0}, B[1005] = {0}, n, j; // 定义变量i, j, n和两个数组A, B。数组大小设为1005
scanf("%d", &n); // 从标准输入读取一个整数n
A[0] = B[0] = 1; // 初始化数组A和B的第一个元素为1,用于存储阶乘的积
// 外层循环从2开始到n,计算每个数的阶乘
for (i = 2; i <= n; i++) {
for (j = 0; j < 1005; j++)
B[j] = 0;
B[0] = 1; // 初始化B数组的第一个元素为1,因为任何数的0阶乘都是1
// 计算i的阶乘,并存储在B数组中
for (j = 0; j < i; j++)
B[j] *= i;
// 处理B数组中的进位
for (j = 0; j < 1005; j++)
if (B[j] > 9) {
B[j + 1] += B[j] / 10;
B[j] %= 10;
}
// 将B数组中的值累加到A数组中
for (j = 0; j < 1005; j++) // 同上,这里应该将100改为1005
{
A[j] += B[j];
if (A[j] > 9) {
A[j + 1] += A[j] / 10;
A[j] %= 10;
}
}
}
// 找到A数组中第一个非零元素的位置
for (i = 1005; i >= 0 && A[i] == 0; i--);
// 从最高位开始打印A数组中的数字,即阶乘和的结果
for (j = i; j >= 0; j--) cout<<A[j]<<endl;
return 0; /
}