题目描述
用高精度计算出 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
题目分析:
思路:
大致推断,50的阶乘已经非常大,更不用说求和,因此精度肯定不够,所以要利用高精度思想
1.外循环完成高精度求和,内循环要完成高精度乘积,如何将每一个数字放进用来做高精度的数组,此处介绍一种方法,进行乘法运算,两个乘数,用一个数乘另一个数的每一位,最后进行进位,如图
所以循环里面就可以直接每次给每一位乘循环数,记得每次成完,要进行进位,也就是
for (j=0; j<100; j++) {//进行乘法之后进位
if (B[j]>9) {
B[j+1] += B[j]/10;
B[j]%=10;
}
}
求和之后也要注意进位,最后输出的时候,也要注意位数,注意因为乘法和减法要求对齐,所以数组里面的数字是反着的,借此达到对齐的想法。
代码:
#include<stdio.h>
/*
此处注释为了解释: for (j=0; j<100; j++) { 这段代码是在干嘛
B[j]*=i;
}
计算多位数的乘法,利用分配律,比如123*13
将123分为100,20,3,直接用13*1,13*2,13*3,得到13|26|39,然后进位,原本的位置留下x/10,进位x%10,
13|29|9,15|9|9,最终答案就是 1599,所以,而每次给数组每一个元素*i。
其实就是乘法,但是这样做之后就会非常巧妙 !!!
*/
int main() {
int i,A[1005]= {0},B[1005]= {0},n,j;
scanf("%d", &n);
A[0]=B[0]=1;
for (i=2; i<=n; i++) {
for (j=0; j<100; j++) {//看上面注释
B[j]*=i;
}
for (j=0; j<100; j++) {//进行乘法之后进位
if (B[j]>9) {
B[j+1] += B[j]/10;
B[j]%=10;
}
}
for (j=0; j<100; j++) {//进行加法进位
A[j]+=B[j];
if (A[j]>9) {
A[j+1] += A[j]/10;
A[j]%=10;
}
}
}
for (i=100; ; i--) {
if(A[i]>0&&i>=0) {
break;
}
}
for (j=i; j>=0; j--) {
printf("%d", A[j]);
}
return 0;
}
本身比较简单,主要是关于求出乘积,其实也可以,第一次将数字赋给数组,然后每次用数组和第几个数字的 i 做乘积,