【洛谷刷题笔记】P1009 [NOIP1998 普及组] 阶乘之和 题解
一、题目:
[NOIP1998 普及组] 阶乘之和
题目描述
用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!+⋯+n!( n ≤ 50 n \le 50 n≤50)。
其中 !
表示阶乘,定义为
n
!
=
n
×
(
n
−
1
)
×
(
n
−
2
)
×
⋯
×
1
n!=n\times (n-1)\times (n-2)\times \cdots \times 1
n!=n×(n−1)×(n−2)×⋯×1。例如,
5
!
=
5
×
4
×
3
×
2
×
1
=
120
5! = 5 \times 4 \times 3 \times 2 \times 1=120
5!=5×4×3×2×1=120。
输入格式
一个正整数 n n n。
输出格式
一个正整数 S S S,表示计算结果。
样例 #1
样例输入 #1
3
样例输出 #1
9
提示
【数据范围】
对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1≤n≤50。
二、题解:
1.思路:
1.使用两个数组 a 和 b 来分别存储阶乘和求和的结果。
2.初始化 a 和 b 数组,将所有元素初始化为 0。
3.从 1 开始循环至 n,分别计算阶乘和累加的结果。
4.对于阶乘部分,使用进位的方式计算,将结果存储在数组 a 中。主要思想:n!=n*(n-1)!
5.对于累加部分,使用进位的方式计算,将结果存储在数组 b 中。注意在一个大循环内。
6.循环结束后,更新数组 b 的长度,最后逆序输出要用。
7.去除数组 b 前导的 0。
8.逆序输出数组 b 中的元素。
2.源码:
#include <iostream>
#include <string.h>
using namespace std;
int a[500];//存储阶乘
int b[500];//存储求和
int main() {
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
int n;
cin >> n;
//n=1时,提前计算,因为大循环从2开始,而阶乘主要思想:n!=n*(n-1)!需要。
a[1] = 1;
b[1] = 1;
//分别记录长度
int la = 1;
int lb = 1;
for (int i = 2; i <= n; i++) {
//n阶乘部分
int carry1 = 0;//处理进位
for (int j = 1; j <= la; j++) {
a[j] = i * a[j] + carry1;
carry1 = a[j] / 10;
a[j] %= 10;
}
while (carry1 > 0) {
a[++la] = carry1 % 10;
carry1 /= 10;
}
//n累加部分
int j;//把j定义在外是因为处理进位和更新b长度要用
int carry2 = 0;//处理进位
for ( j = 1; j <= lb || j <= la; j++) {//注意循环条件
b[j] = b[j] + a[j] + carry2 ;
carry2 = b[j] / 10;
b[j] %= 10;
}
//处理进位
while (carry2 > 0) {
b[++j] = carry2;
}
//更新长度
if (j > lb)
lb++;
}
//去除前导0
while (lb > 1 && b[lb] == 0)
lb--;
//逆序输出
for (int i = lb; i >= 1; i--) {
cout << b[i];
}
}