前言
每每拿到筛质数的题,就迅速敲出代码:
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;
}
已经快得一匹了。
但这种算法并不完美,因为有些合数会被筛两次。
欧拉筛
欧拉筛是对埃氏筛的改进,避免了重复筛,筛完(1sim 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