线性筛
在
O
(
n
)
O(n)
O(n)]时间内得到素数表的一种算法
实现原理:
- 用int primes[]记录素数,st[i]记录i是否为素数
- 每一个数字只会被最小质因子筛掉,对于n而言最小质因子一定出现在 ⩽ n \leqslant \sqrt{\mathrm{n}} ⩽n的范围内
- 可以用均摊分析的方法来分析算法的复杂度,由于每个合数都唯一的被它的最小素因子筛一次,而每个合数的最小素因子都是唯一的,总复杂度是 O ( n ) O(n) O(n)
- 注意,每次筛的都是primes[j]*i
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
int cnt;
int prime[N];
bool st[N];
void get_prime(int n)
{
for(int i = 2; i <= n; i++)
{
if(!st[i]) //如果还没被标记过,就说明这是个质数,就把它加入到primes中
prime[cnt++] = i;
for(int j = 0; prime[j] <= n / i; j++) //确保第j个质数和i相乘不会爆n
{
st[prime[j] * i] = true;
/*
prime[]数组中的素数是递增的,当i能整除prime[j],那么i*prime[j+1]这个合数
肯定被prime[j]乘以某个数筛掉。
因为i中含有prime[j],prime[j]比prime[j+1]小,
即i=k*prime[j],那么i*prime[j+1]=(k*prime[j])*prime[j+1]=k’*prime[j],
接下去的素数同理。所以不用筛下去了。
因此,在满足i%prime[j]==0这个条件之前以及第一次满足改条件时,
prime[j]必定是prime[j]*i的最小因子。
*/
if(i % prime[j] == 0)
break;
}
}
}
int main()
{
int n;
cin >> n;
get_prime(n);
cout << cnt << endl;
for(int i = 0; i<n;++i){
cout<< st[i]<<' ';
}
cout<<endl;
for(int i = 0; i<n;++i){
cout<<prime[i]<<' ';
}
return 0;
}