素数定义
素数,即质数,指在大于 1 1 1的自然数中,除了 1 1 1和它本身以外不再有其他因数的自然数。
判断质数
试除法:
判断是否能被其他
2
2
2~
√
n
√n
√n的数整除,时间复杂度为
O
(
√
n
)
O(√n)
O(√n)
代码:
for(int i=2;i*i<=n;i++)
if(n%i==0)return false;
return true;
筛质数
埃氏筛
简介
埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。
做法
要得到自然数n以内的全部素数,必须把不大于
√
n
√n
√n的所有素数的倍数剔除,剩下的就是素数。
给出要筛数值的范围n,找出以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去…。
时间复杂度为
O
(
n
l
o
g
l
o
g
n
)
O(nloglogn)
O(nloglogn)已经十分接近于线性了。
实现
void prime(int n) {
for(int i = 2;i <= n;i ++) {
if(vis[i])
continue;
bool flag = 1;
for(int j = 2;j * j <= i;j ++) {
if(i % j == 0) {
flag = 0;
break;
}
}
if(flag == 1) {
prim[++cnt] = i;
for(int j = 2;j * i <= n;j ++) {
vis[i * j] = 1;
}
}
}
}
线性筛/欧拉筛
简介
由于我们的合数本质上都可以分解为多个素数的积,因此,在我们使用埃氏筛排除素数的倍数时,会产生重复操作。
当
i
∗
p
r
i
m
e
[
k
]
(
k
>
j
)
i*prime[k](k>j)
i∗prime[k](k>j),一定能找到更大的i,是的
i
∗
p
r
i
m
e
[
k
′
]
(
k
′
<
k
)
=
i
∗
p
r
i
m
e
[
k
]
i*prime[k'](k'<k)=i*prime[k]
i∗prime[k′](k′<k)=i∗prime[k],因此,遇到这种情况时,我么们可以直接break掉。
时间复杂度为
O
(
n
)
O(n)
O(n)也就是线性,很快。
实现
void prime(int x) {
for(int i = 2;i <= x;i ++) {
if(!v[i])
v[i] = i,prim[++cnt] = i;
for(int j = 1;j <= cnt;j ++) {
if(prim[j] > v[i] || prim[j] > x / i)
break;
v[prim[j] * i] = prim[j];
}
}
}