1.朴素筛
-
朴素筛 ,可以看到时间复杂度是从2到x的每个数都会筛选 logn次,所以时间复杂度是O(n log)
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int N = 1000010; int primes[N]; //存储的是剩下的质数以及质数的数量 bool st[N]; int cnt; int n; void shai(int x){ for(int i = 2;i<=x;i++){ if(!st[i]){ //如果是质数的话才加入 primes[cnt++] = i; } for(int j = i + i;j <= n; j++) st[j] = true; } } int main(){ cin>>n; shai(n); cout<<cnt; return 0; }
2.埃式筛
2.埃式筛,就是通过质数,来筛选其他的数,因为一个数肯定可以通过他的质因子来组成,可以看到时间复杂度变成了 (质数数量 * logn * n)
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1000010;
int primes[N]; //存储的是剩下的质数以及质数的数量
bool st[N];
int cnt;
int n;
void shai(int x){
for(int i = 2;i<=x;i++){
if(!st[i]){ //如果是质数的话才加入
primes[cnt++] = i;
for(int j = i + i;j <= n; j++) st[j] = true; //通过质数来筛选
}
}
}
int main(){
cin>>n;
shai(n);
cout<<cnt;
return 0;
}
3.线性筛(欧拉筛)
3.线性筛(也叫欧拉筛),通过最小质因子来筛,只会筛一次,时间复杂度为O(nloglogn)
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1000010;
int primes[N]; //存储的是剩下的质数以及质数的数量
bool st[N];
int cnt;
int n;
void shai(int x){
for(int i = 2;i<=x;i++){
if(!st[i]){ //如果是质数的话才加入
primes[cnt++] = i;
}
for(int j = 0;primes[j] <= x / i;j++){
st[primes[j] * i] = true;
//这里只会出现两种情况
/*
1. primes[j]是i的最小质因子,那么一定是primes[j] * i的最小质因子,那么久可以筛掉
2. primes[j] 不是i的最小质因子,通过下面的语句保证primes[j]比i的最小质因子更小,那么primes[j]一定是
primes[j] * i的最小质因子,那么一定会被筛掉,而且只会筛一次,因为我们遍历了2 -> x的所有数
*/
if(i % primes[j] == 0) break;//到最小质因子筛掉
}
}
}
int main(){
cin>>n;
shai(n);
cout<<cnt;
return 0;
}
- 线性筛在10^7的时间复杂度下大概比埃式筛快一倍