那些年普通的筛法:
for(i=2;i<=sqrt(n);i++)
if(bz[i]) for(j=2;j*i<n;j++) bz[i*j]=0; O(n log n)
其实可以优化:
for(i=2;i<=sqrt(n);i++)
if(bz[i]) for(j=i;j*i<n;j++) bz[i*j]=0;
(因为像3*2 和 2 *3这样的重复了)
其实优化过后就成了Erotosthenes算法O(n log log n)
但是面对数以亿计的数据还是不理想,原因是没有确定一个数被分解的唯一形式。
例:对于12这个数,Erotosthenes算法还是会将其计算两遍(2*6 , 3*4) ,有没有什么方法使每一个数有唯一的分解呢 ?
像12分解为2*2*3(唯一)
现在进入线筛:
设minp[i]表示i最小的质因子是minp[i],例:minp[12]=2 , minp[5]=5
然后:(见代码)
void init()
{
minp[1]=1;
for(int i=2;i<=maxn;i++)
{
if(minp[i]==0) //之前没筛过,是质数
{
pri[++pri[0]] = i; //加入质数表
minp[i]=i; //质数的最小质因子是本身
}
for(int j=1;j<=pri[0];j++) //扫描当前有的质数
{
int k = i* pri[j]; //用i更新其他的数,同其他筛法
if(k > maxn || pri[j] > minp[i]) break;
//退出的条件 :1.要更新的位置超出范围 2.当前枚举的质数比minp[i]大,那么minp[k]!=pri[j]
minp[k] = pri[j];//当前枚举的质数比minp[i]小,i乘上pri[j]最小质因子更新为pri[j]
}
}
return ;
}
这样,每个数只会被最小质因子筛到一次,O(n)。