题目描述
用高精度计算出S = 1! + 2! + 3! + … + n! ( n ≤ 50 ) S = 1! + 2! + 3! + … + n! ( n ≤ 50 )
其中“!”表示阶乘,例如:5! = 5 × 4 × 3 × 2 × 1
输入格式
一个正整数NN。
输出格式
一个正整数S,表示计算结果。
输入输出样例
输入 #
3
输出 #
9
这道题的数据50的阶乘超过了c语言所有数据类型的范围,也就是无法用long long类型,或者unsigned long long来解决
因此这里需要使用【高精度算法】,通俗点说明就是用数据模拟加减乘除
通过查询,学会了该算法的基本形式
(【入门】高精度算法——lazy-sheep :https://blog.csdn.net/zsjzliziyang/article/details/82050337 )
接下来就是应用到该题中了
这道题需要运用到高精度的乘法和加法
高精度算法的基本操作是通过把一个[字符数组]的数据转换成对应的[整数数组]
便可以通过字符数组的strlen()方法来获取数组长度
而在这道题中需要进行手动维护
先上AC代码
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int res[100010], p[100010];///res存放结果, p存放阶乘结果 int len0, len1;///len0维护res长度,len1维护p长度 void Plus() { int len = max(len0, len1); for(int i = 0; i < len; i++){ res[i] = res[i] + p[i]; res[i+1] += res[i]/10; res[i] = res[i]%10; if(res[i] && i >= len0)len0++; } } void Multi(int a) { for(int i = 0; i < len1; i++)p[i] *= a; for(int i = 0; i < len1; i++){ p[i+1] += p[i]/10; p[i] = p[i]%10; if(p[i+1] && i+1 >= len1)len1++; } } int main() { int n; while(scanf("%d", &n) != EOF) { memset(res, 0, sizeof(res)); memset(p, 0, sizeof(p)); res[0] = 0; len0 = len1 = p[0] = 1; for(int i = 1; i <= n; i++) { Multi(i); Plus(); } for(int i = len0-1; i >= 0; i--)printf("%d", res[i]); printf(" "); } }
在乘法中,需要维护的是每次阶乘结果p的长度len1
每当进位的时候就需要对len1加1
void Multi(int a) { for(int i = 0; i < len1; i++)p[i] *= a; for(int i = 0; i < len1; i++){ p[i+1] += p[i]/10; p[i] = p[i]%10; if(p[i+1] && i+1 >= len1)len1++; } }
在加法中,需要注意阶乘的结果p得到的数组长度都会比res长
同样每当进位的时候就需要对长度len0加1
void Plus() { int len = max(len0, len1); for(int i = 0; i < len; i++){ res[i] = res[i] + p[i]; res[i+1] += res[i]/10; res[i] = res[i]%10; if(res[i] && i >= len0)len0++; } }