复合结构程序设计(17)

完数、素数、梅森尼数、双胞胎数

完数

定义:一个数如果恰好等于它的所有真因子之和,这个数就称为“完数”。例如,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 能够完成对输入的数字进行判断 是否为素数? 是否为完数?是否为平方数?等等,那么编程的思路肯定更加清晰!这就是结构化编程中重要的思想,独立功能的模块化设计,也就是自定义函数!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值