题目描述
用高精度计算出 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;
}