目录
质数筛法,是一种快速“筛”出2~n之间所有质数的方法。
1.普通筛法:O(nlogn)
不管是质数还是合数,都用于筛其后面的它的倍数
缺点:一个数被反复筛去浪费了时间
void get_primes(){
for(int i = 2; i <= n; i++){
if(!st[i]) primes[cnt++] = i;//把质数存在primes[]数组里
for(int j = i; j <= n; j += i){//不管是质数还是合数,都用于筛其后面的它的倍数
st[j]=true;
}
}
}
2.埃氏筛法:O(nloglogn)
只用质数就可以把后面的所有合数筛去
优点:比起普通筛法却是节省了一些时间
缺点:但是还是有重复筛掉一个数的操作
void get_primes(){
for(int i = 2;i <= n;i++){
if (st[i]) continue;
primes[cnt++] = i;//把质数存在primes[]数组里
for(int j = i+i;j <= n;j += i)
st[j] = true;//只用质数就可以把后面的所有合数筛去
}
}
3.线性筛法:O(n)
用每个合数的最小质因子筛掉本数
优点:不会对一个合数进行重复筛除
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= n / i; j ++ )
//把primes[j] <= n / i 看成 primes[j] * i <= n
//这样遍历到 >n 时就会自动退出,设置了边界
{
st[primes[j] * i] = true;//将质数倍数筛掉
if (i % primes[j] == 0) break;
//关键判断:
// 1.如果i % primes[j] == 0 说明 prime[j] 是 i 的最小质因子
// 那么如果j继续++的话primes[j + 1] > primes[j],后续被筛掉的数就不是被最小质因子筛去的
// 假设后续被筛掉的数为m,m可以看成m = i * prime(j+1) = k * prime(j) * prime(j+1) (k = i / primes[j])
// 2.如果i % primes[j] != 0 说明 prime[j] 不是 i 的最小质因子,也就可以继续筛了
}
}
}