1. 程式人生 > 實用技巧 >線性篩

線性篩

前言

每每拿到篩質數的題,就迅速敲出程式碼:

bool pd(int n) {
	for(int i=2; i*i<=n; i++)
		if(n%i==0) return 0;
	return 1;
}

然後就獲得了TLE的大禮包……

再不學線性篩是不行了的。

埃氏篩

埃氏篩,全稱埃拉託斯特尼篩法。

列舉每一個數,每個數都有一個標記\(f\) ,如果\(f_i=true\) 代表\(i\) 不是質數,否則是質數。如果列舉到\(i\)\(f_i\)\(false\) ,那麼\(i\) 就是質數,然後把\(n\) 以內的\(i\) 的倍數的數標為\(true\)

  • 注意,\(f\)
    陣列的初始值是\(false\)
for(int i=2; i<=n; ++i)
{
    if(!f[i])
        ++ans;//素數個數+1
    for(int j=2; j*i<=n; ++j)
		f[i*j]=true;
}

已經快得一匹了。
但這種演算法並不完美,因為有些合數會被篩兩次。

尤拉篩

尤拉篩是對埃氏篩的改進,避免了重複篩,篩完\(1\sim n\) 個數的複雜度為\(\mathcal{O}(n)\)

  • \(prime\) 陣列用於記錄所有質數。
for(int i=2;i<=n;++i) {
    if(!visit[i])
        prime[++ans]=i;
    for(int j=1;prime[j]*i<=n&&j<=ans;++j)
	{
        visit[i*prime[j]]=true;
        if(!(i%prime[j]))
			break;
    }
}

P.S.如果不是毒瘤出題人,一般寫埃氏篩就沒啥大問題,但是如果資料大……

此人太菜不會杜教篩、min_25篩和洲閣篩/dk