浅谈线性筛

众所周知,Eratosthenes筛的复杂度是\(O(n\log\log n)\)的,并非严格线性。于是有时候就要用到线性的欧拉筛。


欧拉筛的原理是这样的:

对于每一个数,我们只用它最小的质因子去筛掉它,因此每一个数只会被筛掉一次,从而保证该筛法为线性的。

在实现时,我们需要用数组\(flag_{1,n}\)去表示每一个数是否为质数,并把所有质数从小到大放入数组\(pri_{1,cnt}\)中。若在区间\([1,i]\)共有\(cnt\)个质数,对于\(i\),我们用\(i\)\(pri[j]\)去筛掉\(x = i \times pri[j]\),其中\(j \in [1,\min(cnt,k)], i \mod pri[k] = 0\)。在\(i \mod pri[k] = 0\) 时停止继续往下筛,是因为当\(j > k\)时,\(pri[j]>pri[k]\),而\(pri[k]\)\(i\)的一个因子,也就意味着\(pri[j]\)不再是\(x = i \times pri[j]\)的最小的质因子了,故我们不再往下继续筛,以避免重复计算。

int pri[maxn];    // 存筛出来的素数 

bool flag[maxn];  // flag[i] = false 表示i是素数,flag[i] = true 表示i不是素数 

void work() {
	flag[1] = true;
	for(int i = 2; i <= n; i++) {
		if(!flag[i]) pri[++cnt] = i;
		for(int j = 1; j <= cnt && i * pri[j] <= n; j++) {
			flag[i * pri[j]] = true;
			if(i % pri[j] == 0) break;   // pri[j + 1] 一定不是 i * pri[j + 1] 最小的因子了,停止继续往下筛 
		}
	}
}
posted @ 2020-08-12 15:41  AuroraPolaris  阅读(187)  评论(0编辑  收藏  举报