前言
所谓的筛法就是筛选质数的方法,根据不同的思路有着不同时间复杂度的方法。
暴力(试除法)
从2开始枚举到n - 1,如果能被n整除说明n不是质数。
进一步的简化,从 2 到 枚举;
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
return false;
return true;
}
埃拉托斯特尼筛法
对于任意一个大于1的正整数n,那么它的x倍就是合数( x > 1 )。利用这个结论,我们可以避免很多次不必要的检测。
如果我们从小到大考虑每个数,然后同时把当前这个数的所有(比自己大的)倍数记为合数,那么运行结束的时候没有被标记的数就是素数了。
void Eratosthenes(int n)
{
is_prime[0] = is_prime[1] = false;
for (int i = 2; i <= n; ++i) is_prime[i] = true;
for (int i = 2; i <= n; ++i)
{
if (is_prime[i])
{
prime.push_back(i);
if ((long long)i * i > n) continue;
for (int j = i * i; j <= n; j += i)
is_prime[j] = false;
}
}
}
欧拉筛法
这是一个线性的筛法。在埃式筛法下,让每一个合数只被标记一次,换言之只标记最小的合数,那么他的倍数一定是无法被选取的
void pre(int n)
{
for (int i = 2; i <= n; ++i)
{
if (!not_prime[i])
{
pri.push_back(i);
}
for (int pri_j : pri)
{
if (i * pri_j > n) break;
not_prime[i * pri_j] = true;
if (i % pri_j == 0)
{
break;
}
}
}
}