埃氏筛的定义:
要得到自然数 nn 以内的全部素数,必须把不大于 \sqrt{n}n 的所有素数的倍数剔除,剩下的就是素数。
先用 22 去筛,就是把 22 留下,把22 的倍数剔除掉;再用下一个质数,也就是 33 筛,把 33 留下,把 33 的倍数剔除掉;接下去用下一个质数 55 筛,把 55 留下,把 55 的倍数剔除掉;不断重复。
埃氏筛的时间复杂度:O(n \log n)O(nlogn)。
代码实现
#include<bits/stdc++.h>
using namespace std;
bool is_prime[100005];
//true表示是质数
//false表示不是质数
int main()
{
memset(is_prime,true,sizeof(is_prime));
int n;
cin>>n;
is_prime[0]=is_prime[1]=false;
for(int i=2;i<=sqrt(n);i++){
if(is_prime[i]){
for(int j=2;i*j<=n;j++){
is_prime[i*j]=false;
}
}
}
//x 是不是质数
if(is_prime[n]) cout<<"is_prime";
else cout<<"not_prime";
return 0;
}
欧拉筛
欧拉筛/线性筛总结
欧拉筛是埃氏筛的进阶版。其优化在于每个合数只会被筛掉一次。
1、为什么没有漏掉
答:对于任意合数 Q,假设 Q = p[j] i,其中 p[j] 是 Q 的最小质因子。 意味着不存在任何 k < j,能够使得 i % p[k] == 0。 所以在筛选到 p[j] i 之前,内层循环都不会跳出。
2、为什么没有错误
答:被筛掉的数字都是形如 i p[j] 的形式。 其中 i >= 2,p[j] 为质数,则 i p[j] 必然是合数。
3、为什么只有一次
答:假设有合数 Q = p[x] p[y] q,其中 p[x] 是 Q 的最小质因子。 那么,从上述结论可得:Q 会在 i = p[y] Q 时被筛掉一次。 假设 Q 会被筛掉第二次,在 i =p[x] Q 时被筛掉一次。 这时,当 j = x 时,i % p[j] == 0,内层循环会跳出, 意味着无法枚举到 p[y],也就无法筛掉 p[y] * i。