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)效率的.
线性筛法的作用不只是求素数,以后还会写到其他的应用.