一、埃氏筛
1.原理:
质数的倍数不是质数。
时间复杂度:
O
(
n
l
o
g
2
2
n
)
O(nlog^2_2n)
O(nlog22n)
埃氏筛的时间复杂度不会证明,可戳别处
2.代码
int prm[255], prm_cnt;//存放素数的数组、素数个数
bool iscompos[255];//true代表为合数,false代表素数数
void make_prime(int n) {
if (n <= 1)return;
for (int i = 2; i <= n; i++) {
if (iscompos[i] == 0) {
prm[++prm_cnt] = i;
for (int j = i * i; j <= n; j += i) {
iscompos[j] = 1;
}
}
}
return;
}
二、欧拉筛
1.前言
埃氏筛中,例如21会被3、7同时筛去。
我们希望每个合数仅被筛去一次以提高效率。于是有了欧拉筛。
2.原理
每个合数仅被最小质因子/最大因数筛去
时间复杂度:
O
(
n
)
O(n)
O(n)
每个数仅被处理一次故时间复杂度为
O
(
n
)
O(n)
O(n)
3.代码
//时间复杂度:O(n)
int prm2[maxn], cnt2, tab2[maxn];
void make_prime2(int x) {
if (x <= 1)return;
for (int i = 2; i <= x; i++) {
if (!tab2[i])
prm2[++cnt2] = i;
for (int j = 1; j <= cnt2 && prm2[j] * i < x; j++) { // 枚举素数,筛去倍数
tab2[i * prm2[j]] = 1;
if (!(i % prm2[j])) // 当前数为该素数的倍数,即 prm[j] 为最小质因子
break;
}
}
}
一些后话
- 无论是埃氏筛还是欧拉筛,都可以用
std::bitset
来缩小空间,提高速度(据说bitset
不能优化欧拉筛,反而负优化,但空间确实要小很多) - 筛法思想也可用于一些题目的求解,希望同学们不仅仅只会筛素数。
例如:洛谷P2926 洛谷P7788
朝花夕拾喵~