题目描述
本题为填空题,只需要算出结果
如果一个正整数只有 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;
}