1. 程式人生 > >【數論】線性篩素數,線性篩尤拉函式,求前N個數的約數個數

【數論】線性篩素數,線性篩尤拉函式,求前N個數的約數個數

先來最基本的線性篩素數,以後的演算法其實都是基於這個最基本的演算法:

利用了每個合數必有一個最小素因子,每個合數僅被它的最小素因子篩去正好一次,所以是線性時間。
程式碼中體現在: if(i%prime[j]==0) break;
----------------------------------------------------------------------- 我是低調的分割線 ------------------------------------------------------------------------------------------
然後可以利用這種線性篩法求尤拉函式,需要用到以下幾個性質:
//(1) 若(N%a==0 && (N/a)%a==0) 則有:E(N)=E(N/a)*a;
//(2) 若(N%a==0 && (N/a)%a!=0) 則有:E(N)=E(N/a)*(a-1); 
其中a是N的質因數。
關於尤拉函式還有以下性質:
(1) phi[p]=p-1;  (p為素數);
(2)若N=p^n(p為素數),則 phi[N]=(p-1)*p^(n-1);
關於尤拉函式,Wiki有很詳細的介紹。

-----------------------------------------------------------------------我 是低調的分割線 -----------------------------------------------------------------------------------------
求約數個數略微複雜一點,但大體還是那個意思。
約數個數的性質,對於一個數N,N=p1^a1 + p2^a2 + ... + pn^an。其中p1 ,p2, p3... pn是N的質因數,a1 ,a2, a2,...an為相應的指數,則
                                                           div_num[N]=(p1+1)*(p2+1)*(p3+1)* ... *(pn+1);
結合這個演算法的特點,在程式中如下運用:
  對於div_num:

(1)如果i|prime[j] 那麼 div_num[i*prime[j]]=div_sum[i]/(e[i]+1)*(e[i]+2)                  //最小素因子次數加1
(2)否則 div_num[i*prime[j]]=div_num[i]*div_num[prime[j]]                                     //滿足積性函式條件

  對於e:

(1)如果i|pr[j]  e[i*pr[j]]=e[i]+1; //最小素因子次數加1
(2)否則 e[i*pr[j]]=1;              //pr[j]為1次


hope you got somthing ... :D