前言:先讲一下这两种方法。
埃氏筛法:
一个数的倍数一定为非质数,所以我们每找到一个质数,就枚举它的倍数,将它的倍数都标记为非质数,复杂度nlogn。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
bool prime[20000010];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(prime,1,sizeof(prime));
prime[0]=prime[1]=0;
for(int i=2;i<=n;i++)
{
if(prime[i])
{
for(int j=i+i;j<=n;j+=i)
{
prime[j]=0;
}
}
}
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
if(prime[x])
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}
但显然埃氏筛法对于比较大的范围,比如10^9这样的数显然是不可行的,所以我们需要学习另一种方法。
欧拉筛法:
在埃氏筛的时候我们发现有的数被筛到了很多遍(比如24被2和3都筛过),我们可以在这个地方优化一下。欧拉筛法是将每次找到的质数记录下来,我们每找到一个数,就枚举这个数与我们已有的质数的乘积所得的数,将得到的数标记为非质数,复杂度(O(n))。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int prime[10000010];
bool isprime[10000010];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(isprime,1,sizeof(isprime));
isprime[0]=isprime[1]=0;
int cnt=0;
for(int i=2;i<=n;i++)
{
if(isprime[i])
{
cnt++;
prime[cnt]=i;
}
for(int j=1;j<=cnt;j++)
{
if(i*prime[j]>n)
{
break;
}
isprime[i*prime[j]]=0;
if(i%prime[j]==0)
{
break;
}
}
}
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
if(isprime[x])
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}