快速线性筛法求素数 (模板+简单解释)

首先明确任何合数都能表示成一系列素数的积

第一种易于理解的方法:

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


你可能感兴趣的:(模板)