学习一下这个论文
复杂度为O(n)的线型筛法:
int prime[MAXN], tot;
bool check[MAXN];
void init()
{
FE(i, 2, MAXN)
{
if (!check[i])
prime[tot++] = i;
for (int j = 0; j < tot && i <= MAXN / prime[j]; j++)
{
check[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
}
证明其正确性:
- 保证每个合数能被筛到。(保证正确性)
假设一个合数可以表示为m = p1^n1 * p2^n2 * ...px^nx,那么对于k = p1^(n1 - 1) * p2^n2 * ...px^nx,则m = p1 * k
当i = k时,由素数的性质可知,k不能整除比p1小的任意一个素数。故在prime[j] < p1时,上述代码的13行不会执行到,即此时合数m会被筛到,得证
- 保证每个合数仅被筛一次。(保证复杂度为线性)分两种情况:
此处先证明一下,m一定是被最小的质因子筛掉:
由于m是合数,那么至少含有两个因子,设p为最小的质因子,另一个质因子为p1,m = p * p1 * k
当i = p * k时由于p <= p1,那么当prime[j] = p时执行上述13行的break。
若p < p1,此时不会得到m即m不会因为比p大的数筛掉
若p = p1,此时由于最小的p被筛掉
剩下的只需要证明,m仅有一种质因子的情况:
m = p ^ x, x > 1。设k = p ^ (x - 1)
当i = k时,由素数的性质可知,k不能整除比p小的任意一个素数。故在prime[j] < p时,上述代码的13行不会执行到,即此时合数m会被筛到。
当i = p ^ t, t < x - 1时,同上,在prime[j] < p时,上述代码的13行不会执行到。当prime[j] = p时,此时将会结束i的循环,不会继续向下筛,所以m不会被筛到。
即在此种情况下,合数m仅被筛一次