当求质数时,我们用普通筛法,O(n log n)解决,但n很大时,就会爆掉,这时就需要这一种很强大的筛法——线性筛法来解决,所谓线性,就是O(n)咯。
当我们用普通筛法时,要筛掉一个数n,可能会被筛很多次,这就造成了累赘,比如36:
3 * 12时被筛掉一次,18 * 2时被筛掉一次,这样就会有累赘,那么我们想想:我们在枚举j去筛掉i*j 后 ,如果j|i,(显然j是一个质数)的话,就break掉,就可以变成O(n)了,这样显然是可行的:当筛12 * 2后,2|12,break掉,那这样就不会筛12 * 3,当筛18 * 2的时候,才会真正筛掉36,然后break掉。那么我们就得出了线性筛法的框架:
- 假如i没被筛,加入质数表
- 不管i有没有被筛,从小到大枚举质数j,筛掉i*j,然后如果j|i,break。
Codes:
procedure GetPrimes;
var i,j:longint;
begin
for i:=2 to top do //要求2~top的质数
begin
if not bz[i] then //加入质数表
begin
inc(top);
pr[top]:=i;
end;
for j:=1 to top do //筛掉后面的
begin
if pr[j]*i>top then break;
bz[pr[j]*i]:=true;
if i mod pr[j]=0 then break; //剪掉不必要的
end;
end;
end;
注:x|y表示y mod x=0。