题目描述
用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!+⋯+n!( n ≤ 50 n \le 50 n≤50)。
其中 !
表示阶乘,定义为
n
!
=
n
×
(
n
−
1
)
×
(
n
−
2
)
×
⋯
×
1
n!=n\times (n-1)\times (n-2)\times \cdots \times 1
n!=n×(n−1)×(n−2)×⋯×1。例如,
5
!
=
5
×
4
×
3
×
2
×
1
=
120
5! = 5 \times 4 \times 3 \times 2 \times 1=120
5!=5×4×3×2×1=120。
输入格式
一个正整数 n n n。
输出格式
一个正整数 S S S,表示计算结果。
样例输入
3
样例输出
9
提示
【数据范围】
对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1≤n≤50。
1、刚学习循环时,写出下方的代码就很好
此代码适合的数据范围
1
≤
n
≤
20
1 \le n \le 20
1≤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;
}