蓝桥杯-纯质数,题目分析及代码详细注解,判断质数的方法

题目描述

本题为填空题,只需要算出结果

如果一个正整数只有 1 和它本身两个约数,则称为一个质数(又称素数)。前几个质数是:2,3,5,7,11,13,17,19,23,29,31,37,⋅⋅⋅ 如果一个质数的所有十进制数位都是质数,我们称它为纯质数。例如:2,3,5,7,23,37 都是纯质数,而 11,13,17,19,29,31 不是纯质数。当然 1,4,35 也不是纯质数。请问,在 1 到 20210605 中,有多少个纯质数?

分析题目

纯质数:该数为质数且每一个十进制位都是2、3、5、7中的某一个数。

查找范围:题目为20210605,根据纯质数的定义可知该范围内合理的最大值为7777777,是一个7位数,将8位数的查找范围减小到7位数。

代码思路:先通过埃氏筛筛选出1到7777777之间的质数,然后检查筛选出的数的每一位是否都由2、3、5、7中的数组成,保存符合该条件的数。

代码实现

#include<stdlib.h>
#include<stdio.h>
#include<vector>
#include<set>
using namespace std;
vector<int> prime;//变长数组prime用于保存筛选出的质数
vector<int> result;//变长数组result用于保存从prime中筛选出的纯质数
bool p[7777778]={0};//标志位,在埃氏筛中用于标记p[i]中i是否是为质数,false代表是,truw代表不是
int a[4]={2,3,5,7};//用于与数组prime中数的每一位作比较。
void Find_Prime()//埃氏筛法筛选2到7777777之间的质数
{
	for(int i=2;i<7777778;i++)
	{
		if(p[i]==false)
		{
			prime.push_back(i);
		}
		for(int j=i+i;j<7777778;j+=i)
		{
			p[j]=true;
		}
	}
}
//判断prime中筛选出的数的每一位是否都由2、3、5、7组成,是返回true,否返回false
bool comparison(int number)
{
	set<int> temp;//用于存放从待判断数中的每一位
	while(number>0)
	{
		temp.insert(number%10);
     //由于set不会存放重复元素,故temp.size()大于4至少说明有4个以上数组成该数
	 //(也可以理解为2、3、5、7以外),就一定不是纯质数了
		if(temp.size()>4)
			return false;
		number=number/10;
	}
	//迭代器遍历获得的该数的各位的组成,判断是否都在2、3、5、7中
	for(set<int>::iterator it=temp.begin();it!=temp.end();it++)
	{
		int i;
		for(i=0;i<4;i++)
		{
			if(*it==a[i])
				break;
		}
		if(i==4)
			return false;
	}
	return true;
}
int main()
{
	Find_Prime();
	for(int i=0;i<prime.size();i++)
	{
		if(comparison(prime[i]))
			result.push_back(prime[i]);
	}
	for(int i=0;i<result.size();i++)
	{
		printf("%d\n",result[i]);
	}
	printf("共有纯质数%d个",result.size());
	system("pause");
	return 0;
}

说明

由于计算量大,故点击运行后光标会闪烁大概15秒后开始输出,整个程序的耗时能控制在20秒以内,请耐心等待

 补充

关于埃氏筛法的原理解释

 另一个思路

从[2,3,5,7]中选择m个数,可以选择同一个数如m个2,且m可以大于4的排列组合,直接手动排列出由2、3、5、7组成的所有1到n位数(此步最复杂),再从中判断是否为质数,下图提供一种判断方法,还有一种根据素数两性定理判断是否为素数的方法。

 根据素数两性定理(大于3的素数只能分布在6n-1和6n+1两个数列中,但要注意在6的倍数两侧的也可能不是质数如35,所以要有补充判断)获得1到7777777中的质数,

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
bool is_prime(int x)
{
	if(x==2||x==3)
		return true;
	else if(x%6!=1&&x%6!=5)
		return false;
	for(int i=5;i<(int)sqrt(x*0.1)+1;i+=6)
	{
		if(x%i==0||x%(i+2)==0)
			return false;
	}
	return true;
}
int main()
{
	for(int i=2;i<7777777;i++)
	{
		if(is_prime(i))
			printf("%d\n",i);
	}
	system("pause");
	return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值