I and OI
Past...

1.素数判定

普通的算法即O(sqrt(N))的试除法,高级些的Miller_Rabin素数测试.

但NOIP似乎用不着Miller_Rabin,试除法又非常简单,就不在这里写了.

2.求素数

筛法是比较常见的方法.埃拉托色尼斯筛法可以对付一般的题目了.

但我想写写线性筛法.

先给code:

const MAX=1000000;
var   Prime:array[0..MAX] of longint;
      v:array[0..MAX] of boolean;

      procedure GetPrime;
      var   i,j,tmp,size:longint;
      begin
            size:=0;
            fillchar(v,sizeof(v),0);
            for i:=2 to MAX do
            begin
                  if not v[i] then
                  begin
                        inc(size);
                        prime[size]:=i;
                  end;
                  j:=1;
                  while (j<=size)and(prime[j]*i<MAX) do
                  begin
                        v[i*prime[j]]:=true;
                        if i mod prime[j]=0 then break;
                        inc(j);
                  end;
            end;
      end;

begin
      GetPrime;
end.

算法的核心在于while循环内的语句.

首先,prime[j]一定是i的最小质因子,因此也是i*prime[j]的最小质因子.

然后又有了这句话:if i mod prime[j]=0 then break;

于是算法就保证了每个合数只被它的最小质因子筛去,且仅筛去一次.

那么会不会漏掉某些合数没有筛去呢?不会.

因为i*prime[j'](j'>j)一定被prime[j]乘上以后的某个更大的i'筛去。
∵i'*prime[j]=i*prime[j']
∴i'=i/prime[j]*prime[j']>i

所以是O(N)效率的.

线性筛法的作用不只是求素数,以后还会写到其他的应用.

posted on 2011-08-09 10:38  exponent  阅读(330)  评论(0编辑  收藏  举报