【题目描述】
给定正整数n,求不大于n的正整数的阶乘的和(即求1!+2!+3!+...+n!),输出阶乘的和。
【输入】
输入有一行,包含一个正整数n(1 < n < 12)。
【输出】
输出有一行:阶乘的和。
【输入样例】
5
【输出样例】
153
说明:
主要考查嵌套循环,以及关于数学中阶乘的知识。
本题是一本通中嵌套循环第一题,需要学生了解嵌套循环的运行过程,以及何种问题适合使用嵌套循环解决。
题目概述:
1!+2!+3!+...+n!,阶乘用感叹号"!"表示,3!表示3的阶乘。
所谓阶乘,是等于及小于给定的正整数的乘积。
例如3的阶乘:
3!=1×2×3=6
n!=1×2×3×...×n
题目样例中求5的阶乘:
1!=1
2!=1×2=2
3!=1×2×3=6
4!=1×2×3×4=24
5!=1×2×3×4×5=120
那么1!+2!+3!+4!+5!=1+2+6+24+120=153
思路分析:
本题可以使用一层循环和嵌套循环解决,代码中将展示这两种方法。不过以嵌套循环为主,加深对嵌套循环的理解。
从1!+2!+3!+...+n!可以看出,如果少了感叹号,就是一个普通的等差数列求和,使用一层循环即可。虽然现在求的是阶乘之和,但其原理还是一样的,先看一层循环的实现:
for (int i = 1; i <= n; i++)
sum += i!;
很明显,只要得出i的阶乘,然后像等差数列求和般即可。
再看看求i的阶乘,上面《题目概述》已说明:
i!=1×2×...×i
其实不难看出i!=1×2×...×i和i!=1+2+...+i非常相似,可以说二者只是运算的符号一个是乘号,一个是加号罢了。
很明显,求某个数的阶乘也要用一个循环。符合嵌套循环的使用规则。即求n个数的阶乘之和,外层循环用于遍历1~n每一个数,而内层循环求外层循环当前数字的阶乘。
如果还不明白,可以举个例子:
现有编号为1~10的10个箱子,每个箱子装有不同数量的礼物,要统计10个箱子中所有礼物的数量。
拆开1号箱子,数一数箱子中礼物的数量。
拆开2号箱子,数一数箱子中礼物的数量。
...
拆开10号箱子,数一数箱子中礼物的数量。
全部箱子拆开,并都统计了每个箱子的礼物数量,那么最终的数量就出来了。
该例子与本题求阶乘之和是一样的:
拆开10个箱子相当于10个数的阶乘。
数一数某一个箱子的礼物数量,相当于求某一个数的阶乘。
累计10个箱子的礼物数量,相当于求10个数字的阶乘之和。
外层循环代表的是10个箱子中的每一个箱子,例如当第2次循环时,表示要拆2号箱子。
内层循环代表外层循环中的某个箱子,要在内层循环中算出该箱子的礼物数量。
这就是嵌套循环,作为初学者首先要明白嵌套循环的原理,以及什么情况下适合使用嵌套循环。
数据类型:n(1 < n < 12),经过测试,阶乘之和的最大值不超过int类型的取值范围,可选int类型。
延伸学习:
阶乘的单词是factorial,在编程中,可以缩写为fac。
求解过程:
声明3个int类型变量n、fac、sum = 0,fac用于求每一阶段数字的阶乘,sum用于求所有数的阶乘之和。
输入1个正整数给变量n。
循环n次,i初始为1,循环条件是i<=n,i++,循环体中:
1.fac赋值为1。
2.内层循环,循环i次,j初始为1,循环条件是j<=i,j++,循环体中:
1.将fac乘以j的值赋给fac,即求i的阶乘。
3.将sum加上fac的值赋给sum。
循环外:
输出阶乘之和sum的值。
运行结果:
参考代码 - 嵌套循环:
i是当前要计算阶乘的数,而j是i的阶乘计算范围,范围是1~i,所以内层循环j初始为1,结束为i。
注意代码中语句fac = 1,在计算i的阶乘时,因为是用fac存储i的阶乘,所以先把fac赋值为1,即从1开始相乘。就好比上述数礼物的例子,假设第2个箱子有10个礼物,数第3个箱子的礼物时,不是在第2个箱子的基础上数(即从11开始数),而是从头开始数。每个箱子都是独立的,都应该从1开始数。
#include
using namespace std;
int main(){
int n, fac, sum = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
fac = 1;
for (int j = 1; j <= i; j++)
fac *= j;
sum += fac;
}
cout < return 0;
}
参考代码 - 一层循环(递推算法):
以数箱子礼物为例,嵌套循环的思路是每个箱子的礼物都是独立的,例如1号箱子有10个礼物,2号箱子有20个,3号箱子有30个...
最后把每个箱子的礼物数目加在一起就是总数:
10+20+30+...
即每个箱子都是独立,互不相干的。
现在把每个箱子的礼物数目都在上一个箱子礼物数目的基础上开始数。例如1号有10个,2号从11开始数,3号从31开始数,数到最后就是最终的数目。
求阶乘之和也是一样的道理。
1!=1
2!=1×2=2
3!=1×2×3=6
4!=1×2×3×4=24
5!=1×2×3×4×5=120
相邻两个数的阶乘,后面之数比前面之数多乘了一个数。例如3!比2!多乘了一个3。合并再看看:
1!=1
2!=1!×2=2
3!=2!×3=6
4!=3!×4=24
5!=4!×5=120
其实就是说,求一个数的阶乘时,不必从1开始乘,用上一个数的阶乘再乘以该数就得出该数的阶乘。
有点类似斐波那契数列,第k(k>2)个数是前两数之和。
所以应从第1项开始,不断往后推导,求得一个数的阶乘时,立即累计在sum中,下次循环时,不把fac初始为1,而是继续与下个数相乘。
这就是递推算法,可以使用递归或迭代来实现。
#include
using namespace std;
int main(){
int n, fac = 1, sum = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
fac *= i;
sum += fac;
}
cout < return 0;
}
END
注:题目来源于网络,转载于《信息学奥赛一本通(C++版)在线评测系统》,点击下方的【阅读原文】即可打开该题的链接。
题解属于本微信公众号【大神编程】原创。