题目描述
用高精度计算出 S=1!+2!+3!+⋯+n!(n≤50)。
其中 !
表示阶乘,定义为 n!=n×(n−1)×(n−2)×⋯×1。例如,5!=5×4×3×2×1=120。
输入格式
一个正整数 n。
输出格式
一个正整数 S,表示计算结果。
输入输出样例
输入 #1
3
输出 #1
9
解题分析
思路很简单,求出阶乘之后再累次求和即可,但是关键在于这个数据量实在是太大了,所以必须封装高精度运算,这里我们创建一个BigInt类,然后重载运算符+和*,得出答案即可。
这段代码定义了一个 BigInt
类来处理大整数的运算,这对于计算大数的阶乘和它们的和是必需的,因为标准的整型变量无法存储这么大的数字。接下来,我们会逐步解释关键的组成部分,尤其是高精度的加法和乘法。
构造函数
BigInt
类有两个构造函数,分别接受一个整数和一个字符串作为参数。整数构造函数将整数转换为字符数组(字符串表示),而字符串构造函数则直接复制给定的字符串到内部字符数组。转换整数时,采用逆序存储的方式,方便后续的加法和乘法运算。
高精度加法
高精度加法的实现在 operator+
函数中。它首先将两个大整数的字符串表示逆序存储到整型数组中,然后逐位相加,并处理进位。由于加法可能导致结果的位数增加(例如,999 + 1 = 1000),因此需要预留足够的空间并在最后处理进位。加法完成后,将得到的数字逆序转换成字符串形式,得到最终的加法结果。
高精度乘法
高精度乘法的实现在 operator*
函数中。该函数使用了一个简单的乘法运算法则,即对于两个数的每一位相乘,并将结果累加到正确的位置上。这里同样使用了逆序存储和处理进位。乘法的复杂度较高,因为它涉及到双层循环,每一位的乘积都需要计算并累加进位。
阶乘与求和
factorial
函数计算给定整数的阶乘,通过从 2 乘到 n 的方式,使用前面定义的高精度乘法。
在 main
函数中,读取用户输入的 n
,然后从 1 遍历到 n
,计算每个数的阶乘,并使用高精度加法将它们累加起来。最终,将结果输出。
示例
对于输入 3,计算 1! + 2! + 3!
的结果:
1! = 1
2! = 2
3! = 6
因此,1! + 2! + 3! = 9
。
这段代码通过高精度运算支持了对大数的阶乘及其和的计算,解决了标准数据类型无法处理大数运算的问题。
代码实现
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
class BigInt{
public:char s[3000];BigInt(int n){char c;int k=0;if(n==0){s[0]='0';s[1]='\0';k=1;}while(n){c=n%10+'0';s[k++]=c;n/=10;}s[k]='\0';for(int i=0,j=k-1;i<=j;i++,j--){c=s[i];s[i]=s[j];s[j]=c;}}BigInt(const char *s1){strcpy(s,s1);}BigInt operator+(const BigInt &b){int lena=strlen(s);int lenb=strlen(b.s);int a1[3000],b1[3000],c[3000]={0};for(int i=0,j=lena-1;i<lena;i++,j--){a1[i]=s[j]-'0';}for(int i=0,j=lenb-1;i<lenb;i++,j--){b1[i]=b.s[j]-'0';}int len=lena+lenb;int tmp=0;for(int i=0;i<len;i++){c[i]=a1[i]+b1[i]+tmp;tmp=c[i]/10;c[i]%=10;}char ans[3000];int pos=0;for(int i=len;i>=0;i--){if(c[i]){pos=i+1;break;}}for(int i=0,j=pos-1;i<pos;i++,j--){ans[i]=c[j]+'0';}ans[pos]='\0';if(pos==0){ans[0]='0';ans[1]='\0';}return BigInt(ans);}BigInt operator*(const BigInt &b){int lena=strlen(s);int lenb=strlen(b.s);int a1[3000],b1[3000],c[3000]={0};for(int i=0,j=lena-1;i<lena;i++,j--){a1[i]=s[j]-'0';}for(int i=0,j=lenb-1;i<lenb;i++,j--){b1[i]=b.s[j]-'0';}int len=lena+lenb+2;int jw;for(int i=0;i<lena;i++){jw=0;for(int j=0;j<lenb;j++){c[i+j]+=a1[i]*b1[j]+jw;jw=c[i+j]/10;c[i+j]%=10;}c[i+lenb]=jw;}char ans[3000];int pos=0;for(int i=len;i>=0;i--){if(c[i]){pos=i+1;break;}}for(int i=0,j=pos-1;i<pos;i++,j--){ans[i]=c[j]+'0';}ans[pos]='\0';if(pos==0){ans[0]='0';ans[1]='\0';}return BigInt(ans);}
};BigInt factorial(int n){BigInt ans(1);for(int i=2;i<=n;i++){ans=ans*BigInt(i);}return ans;
}int main(){BigInt res(0);int n; cin>>n;for(int i=1;i<=n;i++){res=res+factorial(i);}cout<<res.s<<endl;return 0;
}