素数的定义:
只含有1和它本身两个因子的数称之为素数,1除外——《数学女孩》(图灵新知)
第1种: 朴素做法 O(n^2)
从素数的定义我们很容易得到下列的做法
for i 2 to n-1
if n/i==0
为合数
否则为素数
一个简单的常数优化: 既除2以外,只需判断所有的奇数是否是素数
因为显而易见2是合数 那么所有2的倍数也必然是合数
第2种:O(n^1/2)一个更加高效的优化
对正整数n,如果用2到sqrt(n)之间的所有整数除
均无法整除,则n为质数。
if(x<2) return false;
if(x==2) return true;
for(int i=2;i*i<=x;i++)
if(x%i==0) return false;
return true;
第3种 埃式筛(nloglong)
显而易见的 一个质数的倍数不可能是质数
所以我们从2开始 每次从最小的数开始
将它的倍数全部筛掉
最后得到的就是素数表
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
bool prime[maxn];
void init(int &n)
{
for(int i=2;i<=n;i++)
{
prime[i]=true;//先对prime数组进
行初始化
}//默认情况下所有数都是素数
}
void op(int &n)
{
for(int i=2;i*i<=n;i++)
if(prime[i])//如果是素数的话 将除去它本身外的所有倍数都
for(int j=i*i;j<=n;j+=i)//false
prime[j]=false;
}
int main()
{
int n;
cin>>n;
init(n);
op(n);
for(int i=2;i<=30;i++)
cout<<i<<" "<<prime[i]<<endl;
return 0;
}
方法4 欧拉筛(线性筛)
相比较与方法4的埃式筛法 欧拉筛将原来的每个数被他的因子筛掉变成了每个数被他的最小因子筛掉 并引进了素数表这个元素 用来记录已经存在的素数 进一步减少了时间复杂度
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
bool prime[maxn];
vector<int> primes;
void init(int &n)
{
for(int i=2;i<=n;i++)
prime[i]=true;//初始化令所有数都为素数
primes.clear();//清空素数表
}
void op(int &n)
{
for(int i=2;i<=n;i++)
{
if(prime[i])//如果为素数
primes.emplace_back(i);//则加入素数表
for(auto&x:primes)//每次循环 筛掉素数表的倍数
{
if(x*i>n) break;//超出范围则停止
prime[x*i]=false;//将倍数筛掉
if(i%x==0) break;//如果i为x倍数 则中断
}
}
}
int main()
{
int n;
cin>>n;
init(n);
op(n);
for(int i=2;i<=n;i++)
if(prime[i]) cout<<i<<" ";
return 0;
}