快速線性篩法求素數 (模板+簡單解釋)
阿新 • • 發佈:2019-02-03
首先明確任何合數都能表示成一系列素數的積
第一種易於理解的方法:
注意對1的預處理即可,空間較大
var
n,m,x,t :longint;
i,j :longint;
prime :array[0..10000010] of longint;
vis :array[0..10000010] of boolean;
begin
read(n,m);t:=0;
vis[1]:=true;
for i:=2 to n do
begin
if not vis[i] then
begin
inc(t);
prime[t]:=i;
end;
for j:=1 to t do
if (i*prime[j]>n) then break else
begin
vis[i*prime[j]]:=true;
if (i mod prime[j]=0) then break;
end;
end;
for i:=1 to m do
begin
read(x);
if vis[x] then writeln('No') else writeln('Yes');
end;
end.
另一種時空效率都不錯的方法,不太容易理解:
var
half,t,n,m,x,k :longint;
prime :array[0..5000010] of boolean;
i,j :longint;
begin
read(n,m);
half:=n div 2;t:=trunc(sqrt(n));
for i:=0 to half do prime[i]:=true;
for i:=0 to t do
if prime[i] then
begin
k:=i+i+3;
j:=k*i+i+k;
while (j<=half) do
begin
prime[j]:=false;
inc(j,k);
end;
end;
for i:=1 to m do
begin
read(x);
if (x=2) then writeln('Yes') else
if (x mod 2=0) then writeln('No') else
if prime[(x-3) div 2] then writeln('Yes') else writeln('No');
end;
end.
簡單解釋一下:
首先偶數除了2其他全都是合數所以特判一下2其他的偶數全都不考慮
那麼我們只考慮奇數,那麼我們就只剩下half個數字
由於1不是質數,那麼從3開始考慮
對於prime陣列,表示的數和下標對應的關係
表示的數:3 5 7 9 11 13 15
下標: 0 1 2 3 4 5 6
顯然,可以得到,對於prime[i]表示的數為2*i+3(i=0,1,2,3......half)
那麼,數字的範圍即trunc(sqrt(n))
舉個例子,3是質數,那麼我們就要把3*3,3*5,3*7...置成false,它們對應的下標為3、6、 9....
一般化,即:
如果prime[i]為質數,
令k=2*i+3,那麼prime[j]=false ( j=k*i+k+i*l*k(l=0,1,2,....) )
——by Eirlys