题目描述
用高精度计算出 S=1!+2!+3!+⋯+n!S = 1! + 2! + 3! + \cdots + n!S=1!+2!+3!+⋯+n!(n≤50n \le 50n≤50)。
其中 !
表示阶乘,定义为 n!=n×(n−1)×(n−2)×⋯×1n!=n\times (n-1)\times (n-2)\times \cdots \times 1n!=n×(n−1)×(n−2)×⋯×1。例如,5!=5×4×3×2×1=1205! = 5 \times 4 \times 3 \times 2 \times 1=1205!=5×4×3×2×1=120。
输入格式
一个正整数 nnn。
输出格式
一个正整数 SSS,表示计算结果。
样例输入
3
样例输出
9
提示
【数据范围】
对于 100%100 \%100% 的数据,1≤n≤501 \le n \le 501≤n≤50。
1、刚学习循环时,写出下方的代码就很好
此代码适合的数据范围1≤n≤201 \le n \le 201≤n≤20
通过计算器计算发现,20的阶乘大约是2.4x1018 ,而1 ~ 19的阶乘和是小于20的阶乘的,因此1 ~ 20 的阶乘和小于两倍的20的阶乘,即4.8x1018 。用long long可以存下。提交代码可以得50分。
1.1、一般代码
#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
//s用于累计阶乘的和,x用于存储i的阶乘
long long s = 0, x = 1;
for (int i = 1; i <= n; i++) {
//计算i的阶乘
x = 1; //将x重置为1
for (int j = 1; j <= i; j++)
x *= j;
//累加阶乘的和
s += x;
}
cout << s;
return 0;
}
1.2、优化后的代码
//优化规则:n的阶乘等于(n-1)的阶乘*n,所以不用每次都重新从1开始乘到i,来计算i的阶乘
#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
//s用于累计阶乘的和,x用于存储i的阶乘
long long s = 0, x = 1;
for (int i = 1; i <= n; i++) {
//计算i的阶乘
x *= i; //n的阶乘等于(n-1)的阶乘*n
//累加阶乘的和
s += x;
}
cout << s;
return 0;
}
2、高精度计算代码
//满分代码,学了高精度计算之后再来研究
#include<iostream>
#include<cstring>
using namespace std;
//a数组用于乘法运算,初值是1;sum数组用于阶乘的累加,初值是0
//a[0]中保存a中数字的位数,s[0]中保存s中数字的位数
int a[500],sum[500];
void mul(int x)//高精乘
{
for(int i=1;i<=a[0];i++)
a[i]*=x;
for(int i=1;i<=a[0];i++)
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
//找到最高位
int t=a[0];
while(a[t+1]>0)
t++;
//处理进位
while(a[t]>10)
{
a[t+1]+=a[t]/10;
a[t]%=10;
t++;
}
a[0]=t; //记录数字的位数
}
void add()//高精加
{
if(sum[0]<a[0])
sum[0]=a[0];
for(int i=1;i<=sum[0];i++)
{
sum[i]+=a[i];
sum[i+1]+=sum[i]/10;
sum[i]%=10;
}
//计算数字的位数
if(sum[sum[0]+1]>0)
sum[0]+=1;
}
int main()
{
int n;
cin>>n;
a[0]=1;a[1]=1;sum[0]=1;sum[1]=0;
for(int i=1;i<=n;i++)
{
mul(i);//计算i的阶乘
add();//累计阶乘和
}
//输出结果
for(int i=sum[0];i>=1;i--)
cout<<sum[i];
cout<<endl;
return 0;
}