完数、素数、梅森尼数、双胞胎数
完数
定义:一个数如果恰好等于它的所有真因子之和,这个数就称为“完数”。例如,6的真因子为1,2,3,而6=1+2+3
题目:求1000以内的所有完数之和。
思路:大结构用计数循环,关键是循环体内的判断问题;可以降低难度,从判断一个数是否为完数开始;根据定义求出该数X的所有真因子即可,因子-》范围 【1,X-1】用循环!
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
int main()
{
int i,sum=0,j,t;
for(i=1;i<=1000;i++)
{
t =0 ;
for(j=1;j<i;j++)
{
if(i%j==0) t+=j;
}
if(t==i) sum+=i;
}
cout<<sum<<endl;
// printf("%d\n",sum);
return 0;
}
注意点:t 用来统计每个 i 的真因子和,所以需要写循环体(重复清0,以前的 i 的统计结果不能影响当前),清0也有重复的! 另外,j 循环的起止条件要小心(真因子)。
素数
定义:除1和本身外再无其它因子的数(大于等于2)
题目:输出【2,1000】所有素数。
思路:根据完数思路,很容易解决
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
int main()
{
int i,j,t;
for(i=2;i<=1000;i++)
{
t =0 ;
for(j=2;j<i;j++)
{
if(i%j==0) t++;
}
if(t==0)
cout<<i<<" ";
//printf("%6d",i);
}
return 0;
}
注意点:为什么能够马上就确定1000000不是素数?需不需要从2到999999全部都算一遍呢?很显然不需要,所以程序可以改进,遇到一个非1和本身的因子就跳出循环(不是素数)。甚至t这个变量都可以不需要定义! 至于 j < i 也可以换成 j <= sqrt(i)
int main()
{
int i,j;
for(i=2;i<=1000;i++)
{
for(j=2;j <=(int) sqrt(i);j++)
{
if(i%j==0) break;
}
if(j > (int) sqrt(i))
cout<<i<<" ";
//printf("%6d",i);
}
return 0;
}
梅森尼数
定义:指能使2^n - 1为素数的数
题目:求[2,21]范围内有多少个梅森尼数? 思路(略)
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
int main()
{
int i,j,t,sum=0;
for(i=2;i<=21;i++)
{
// t=pow(2,i)-1;
t=( 1 << i )- 1;
for(j=2;j <=(int) sqrt(t);j++)
{
if(t%j==0) break;
}
if(j > (int) sqrt(t)) sum++;
}
cout<<sum<<endl;
//printf("%d\n",sum);
return 0;
}
注意点:移位运算效率远高于求平方、乘法运算;要注意 2 ^ i - 1 应该是 t=( 1 << i )- 1;移位运算优先级低于算术运算,需要用括号。
双胞胎数
定义:两个素数之差为2,则称这两个素数为双胞胎数。
题目:输出【200,1000】所有的双胞胎数。
思路:按照素数的方法进行求解,分别对 i 和 i + 2 判断是否同时为素数
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
int main()
{
int i,j,t;
for(i=200;i<=1000;i++)
{
for(j=2;j<i;j++)
{
if(i%j==0) break;
}
if(j==i) //i是素数,再去判断 i+2
{
for(j=2;j<i+2;j++) //照葫芦画瓢,再来一次i + 2
{
if((i + 2) % j==0) break;
}
if(j==i+2) //i + 2也是素数
cout<<i<<","<<i+2<<endl;
}
}
return 0;
}
能够一口气完成双胞胎数的求解,应该说复合结构程序设计的基础非常不错了。
1、有没有改进方法
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
int main()
{
int i,j;
for(i=200;i<=1000;i++)
{
for(j=2;j<i;j++)
{
if(i%j==0 || ( i + 2) %j ==0) break;
}
if(j==i) cout<<i<<","<<i+2<<endl;
}
return 0;
}
如果是【2,1000】会多出一组错误解 2 ,4 怎么解决?
为什么不是 for(j=2;j<i+2;j++)
int main()
{
int i,j;
for(i=200;i<=1000;i++)
{
for(j=2;j<i+2;j++)
{
if((i%j==0 && i != j) || ( i + 2) %j ==0) break;
}
if(j==i+2) cout<<i<<","<<i+2<<endl;
}
return 0;
}
2、如果有一个功能函数:比如 fun 能够完成对输入的数字进行判断 是否为素数? 是否为完数?是否为平方数?等等,那么编程的思路肯定更加清晰!这就是结构化编程中重要的思想,独立功能的模块化设计,也就是自定义函数!