全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之循环结构(for循环语句)—(十)(求解数学中特殊的数)
实战训练1—完全数
问题描述:
数学上的“完全数”是指真因子(除了自身以外的约数)之和等于它本身的自然数。例如,6的因子是1,2,3,而1+2+3=6,所以6是完全数。如果一个正整数小于它的所有真因数之和,被称为“不足数”。如果一个正整数大于它的所有真因数之和,被称为“过剩数”。编程实现判断一个正整数是完全数、不足数还是过剩数。
输入格式:
输入一行,包含一个正整数n
输出格式:
输出一行,如果n是完全数,则输出"Perfect",不足数则输出"Deficient",过剩数则输出"Abundant"。
输入输出样例:
输入样例1 | 输出样例1 |
28 | Abundant |
输入样例2 | 输出样例2 |
11 | Deficient |
输入样例3 | 输出样例3 |
36 | Abundant |
问题分析:
根据题意,对于正整数n需要计算其所有正因子(不包括它本身)的和,借鉴求素数的思想,从1开始到n-1结束依次去整除n,使用循环来实现,循环变量i初始值为1,终值为n-1,更新表达式为自增运算,循环体内循环变量依次去整除n,如果n%i==0,那么将i累加到因子和,最后判断因子和是否等于它本身,等于则这个数是完全数,小于则为不足数,否则为过剩数。具体程序代码如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
int n,sum=0;//定义正整数n和,因子和变量sum并初始化为0
cin>>n;//输入n
for(int i=1; i<n; i++) {//定义循环变量i,从1到n-1
if(n%i==0) {//循环变量i依次去整除n,判断i是否为n的因子
sum += i;//将因子i累加到和变量sum中
}
}
if(sum==n) {//判断sum是否和该数相等
cout<<"Perfect"<<endl;//完全数
} else if(sum>n) {//判断sum是否大于n
cout<<"Abundant"<<endl;//过剩数
} else {
cout<<"Deficient"<<endl;//不足数
}
return 0;
}
在判断素数时,对代码进行了改进,每个数的因子是成对出现的,所以找到一个因子之后,让n去除以该因子得到另一个因子,当然需要考虑这两个因子是否相等,同时需要将该数本身去除出去,可以将循环变量的终值修改为sqrt(n),这样减少了代码循环次数,提高了效率。具体程序代码如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
int n,sum=0;//定义正整数n和,因子和变量sum并初始化为0
cin>>n;//输入n
for(int i=1; i<=sqrt(n); i++) {//定义循环变量i,从1到sqrt(n)
if(n%i==0) {//循环变量i依次去整除n,判断i是否为n的因子
if(i != n/i){//判断两个因子是否相等,如果不相等进入本分支
sum += i;//将因子i累加到和变量sum中
if(n/i != n){//需要考虑i为1时,另一因子是该数本身,所以不能将本身累加到和sum中
sum += n/i;//将另一个因子n/i累加到和变量sum中
}
}else{//两个因子相等
sum += i;//两个因子相等只需累加一次
}
}
}
if(sum==n) {//判断sum是否和该数相等
cout<<"Perfect"<<endl;//完全数
} else if(sum>n) {//判断sum是否大于n
cout<<"Abundant"<<endl;//过剩数
} else {
cout<<"Deficient"<<endl;//不足数
}
return 0;
}
实战训练2—寻找指定范围的完全数
问题描述:
数学上的“完全数”是指真因子(除了自身以外的约数)之和等于它本身的自然数。例如,6的因子是1,2,3,而1+2+3=6,所以6是完全数。输入两个整数m和n,且m<=n,输出m到n这个范围内所有的完全数。
输入格式:
输入一行,两个整数m和n,且m<=n。
输出格式:
输出一行,输出所有的完全数,完全数之间用一个空格隔开。
输入输出样例:
输入样例 | 输出样例 |
2 10001 | 6 28 496 8128 |
问题分析:
通过实战训练2可知判断一个整数是否为完全数时采用单层循环,现在该训练修改为统计某个范围内的完全数,即对该范围内的所有整数,依次去判断该整数是否为是否为完全数,因此需要采用for循环嵌套来实现,外层循环变量i表示整数范围m到n,内层循环变量j表示是否为i的因子,j的取值从1到i-1,用j去整除i。具体程序代码如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
int m,n;//定义正整数范围m和n
cin>>m>>n;//输入m和n的值
for(int i=m;i<=n;i++){//定义外层循环,循环变量i从m到n
int sum =0;//定义因子和变量sum,并初始化为0
for(int j=1;j<i;j++){//定义内层循环,循环变量j依次去整除i,判断j是否为i的因子
if(i%j==0){//如果i能被j整除
sum += j;//将因子j累加到和变量sum中
}
}
if(sum == i){//如果因子和等于该数本身,则为完全数
cout<<i<<" ";//输出该完全数i
}
}
return 0;
}
同理将内层循环的终值值设置为sqrt(i),程序代码如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
int m,n;//定义正整数范围m和n
cin>>m>>n;//输入m和n的值
for(int i=m; i<=n; i++) { //定义外层循环,循环变量i从m到n
int sum =0;//定义因子和变量sum,并初始化为0
for(int j=1; j<=sqrt(i); j++) {//定义循环变量j,从1到sqrt(i)
if(i%j==0) {//循环变量j依次去整除i,判断j是否为i的因子
if(j != i/j) { //判断两个因子是否相等,如果不相等进入本分支
sum += j;//将因子j累加到和变量sum中
if(i/j != i) { //需要考虑j为1时,另一因子是该数本身,所以不能将本身累加到和sum
sum += i/j;//将另一个因子i/j累加到和变量sum中
}
} else { //两个因子相等
sum += j;//两个因子相等只需累加一次
}
}
}
if(sum == i) { //如果因子和等于该数本身,则为完全数
cout<<i<<" ";//输出该完全数i
}
}
return 0;
}