1. 程式人生 > >快速線性篩法求素數 (模板+簡單解釋)

快速線性篩法求素數 (模板+簡單解釋)

首先明確任何合數都能表示成一系列素數的積

第一種易於理解的方法:

注意對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