质数筛法:朴素素数筛,埃氏筛,欧式筛
若一个数可以进行因数分解,则得到的两个数一定是有一个>=sqrt(x),另一个<=sqrt(x).
朴素算法
这个算法是最简单的素数判断算法+遍历素组,耗时长
bool judge(ll x)
{
if(x==2) return true;
if(x<2||x%2==0)
return false;
for(int i=3;i<=sqrt(x+1);i+=2)//这个地方可以优化一下,一个是范围,一个是步长 (素数一定是奇数)
{
if(x%i==0)
return false;
}
return true;
}
埃氏筛
利用当前已经找到的素数,从后面的数中筛去当前素数的倍数,当前素数已经是筛去数的质因子,如此下去能筛除之后所有的合数,是一种比较快的筛法美中不足是会筛除多次比如8和16,同时被2和4筛去
输入数据
100 2
2
91
输出数据
Yes
No
#include <bits/stdc++.h>
using namespace std;
int prime[10000005];
const int N = 10000000;
void isprime()
{
fill(prime,prime + N,true);
prime[1] = false;
for(int i = 2; i <= N; ++i)
{
if(prime[i])
{
for(int j = i * 2;j <= N;j += i)
{
prime[j] = false;
}
}
}
}
int main()
{
isprime();
int n,m;
cin>>n>>m;
int num;
for(int i = 0;i < m;i++)
{
cin>>num;
if(prime[num])
cout<<"Yes\n";
else
cout<<"No\n";
}
return 0;
}
欧式筛
这是一种很好的线性筛法,和埃氏筛法的区别是对于每一个要筛除的数,欧拉筛法只筛除一次。原理如下
任何一个合数都可以表示成一个质数和一个数的乘积
假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:
A = x * y; (假设y是质数,x合数)
x = a * b; (假设a是质数,且a < x——>>a<y)
-> A = a b y = a Z (Z = b y)
即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积,那样我们到每一个数,都处理一次,这样处理的次数是很少的,因此可以在线性时间内得到解。
#include <bits/stdc++.h>
using namespace std;
int prime[10000005];
int primesize = 0;
bool isprime[10000005];
void getlist(int listsize)
{
memset(isprime,1,sizeof(isprime));
isprime[1] = false;
for(int i = 2;i <= listsize;i++)
{
if(isprime[i])
{
prime[++primesize] = i;
}
for(int j = 1;j <= primesize && i * prime[j] <= listsize;j++)
{
isprime[i * prime[j]] = false;
if(i%prime[j] == 0)
break;
}
}
}
int main()
{
int n,m;
cin>>n>>m;
getlist(n);
int num;
for(int i = 0;i < m;i++)
{
cin>>num;
if(isprime[num])
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}
return 0;
}