• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            M.J的blog

            algorithm,ACM-ICPC
            隨筆 - 39, 文章 - 11, 評論 - 20, 引用 - 0
            數據加載中……

            【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數

            先來最基本的線性篩素數,以后的算法其實都是基于這個最基本的算法:
             1 #include<stdio.h>
             2 #include<string.h>
             3 #define M 10000000
             4 int prime[M/3];
             5 bool flag[M];
             6 void get_prime()
             7 {
             8     int i,j,k;
             9     memset(flag,false,sizeof(flag));
            10     k=0;
            11     for(i=2;i<M;i++){
            12         if(!flag[i])                            
            13         prime[k++]=i;
            14         for(j=0;j<k&&i*prime[j]<M;j++){
            15             flag[i*prime[j]]=true;            
            16             if(i%prime[j]==0)             
            17                 break;
            18         }
            19     }
            20 }
            21 int main()
            22 {}
             

            利用了每個合數必有一個最小素因子,每個合數僅被它的最小素因子篩去正好一次,所以是線性時間。
            代碼中體現在: 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有很詳細的介紹。

             1 #include<stdio.h>
             2 #include<string.h>
             3 #define M 10000000
             4 int prime[M/3],phi[M];
             5 bool flag[M];
             6 void get_prime()
             7 {
             8     int i,j,k;
             9     memset(flag,false,sizeof(flag));
            10     k=0;
            11     for(i=2;i<M;i++){
            12         if(!flag[i]){                            
            13             prime[k++]=i;
            14             phi[i]=i-1;
            15         }
            16         for(j=0;j<k&&i*prime[j]<M;j++){
            17             flag[i*prime[j]]=true;            
            18             if(i%prime[j]==0){
            19                 phi[i*prime[j]]=phi[i]*prime[j];
            20                 break;
            21             }
            22             else
            23                 phi[i*prime[j]]=phi[i]*(prime[j]-1);
            24         }
            25     }
            26 }
            27 int main()
            28 {}

            -----------------------------------------------------------------------我是低調的分割線-----------------------------------------------------------------------------------------
            求約數個數略微復雜一點,但大體還是那個意思。
            約數個數的性質,對于一個數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次

             1 #include<stdio.h>
             2 #include<string.h>
             3 #define M 10000000
             4 int prime[M/3],e[M/3],div_num[M];           // e[i]表示第i個素數因子的個數
             5 bool flag[M];
             6 void get_prime()
             7 {
             8     int i,j,k;
             9     memset(flag,false,sizeof(flag));
            10     k=0;
            11     for(i=2;i<M;i++){
            12         if(!flag[i]){                            
            13             prime[k++]=i;
            14             e[i]=1;
            15             div_num[i]=2;                       //素數的約數個數為2
            16         }
            17         for(j=0;j<k&&i*prime[j]<M;j++){
            18             flag[i*prime[j]]=true;            
            19             if(i%prime[j]==0){
            20                 div_num[i*prime[j]]=div_num[i]/(e[i]+1)*(e[i]+2);
            21                 e[i*prime[j]]=e[i]+1;
            22                 break;
            23             }
            24             else{
            25                 div_num[i*prime[j]]=div_num[i]*div_num[prime[j]];
            26                 e[i]=1;
            27             }
            28         }
            29     }
            30 }
            31 int main()
            32 {}
            33 
            34 
            35 
            希望大家有所收獲~~                        
             Made by  M.J

            posted on 2010-04-28 16:56 M.J 閱讀(3773) 評論(11)  編輯 收藏 引用

            評論

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數[未登錄]  回復  更多評論   

            性能如何?
            2010-04-28 17:37 | chaogu

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            線性的,復雜度在信息學競賽中已經相當優(yōu)化了。~@chaogu
            2010-04-28 22:50 | M.J

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            沒太看懂,lz說的求前N個數的約數個數,是指
            拿1 2 3 為例
            1 | 1,1 | 2,1 | 3
            2 | 3,
            3 | 3
            結果是6?是這意思嗎
            2010-04-29 12:22 | schindlerlee

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            你好。這個程序是求前N個數所有數的約數的個數。拿M=100來說,程序跑完后可以得到2到100所有數的約數個數。。~@schindlerlee
            2010-04-29 16:40 | M.J

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            謝謝 研究下你這個求約數個數的程序 感覺挺有用的 呵呵,如果你這個模板可以直接用就更好了哈
            2010-05-03 16:20 | abilitytao

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            呵呵,應該可以做做成模板,只不過一般比賽應該不會出這么直接的題哈~!不過這個思想挺有用的,而且這幾個程序確實很快。@abilitytao
            2010-05-06 22:59 | M.J

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            好東西,頂~
            2010-07-19 16:13 | dlut_thinkers

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            2: 2
            3: 2
            4: 3
            5: 2
            6: 4
            7: 2
            8: 4
            9: 3
            10: 4
            11: 2
            12: 8
            13: 2
            14: 4
            15: 4
            16: 5
            17: 2
            18: 6
            19: 2
            20: 8
            20的約數個數是不是應該是6?
            2010-08-08 17:26 | lzbltx

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數[未登錄]  回復  更多評論   

            @lzbltx
            是的。對了,這個程序的數組e[]我開小了,應該開M這么大,不是M/3.
            2010-08-17 22:01 | M.J

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            Orz下!
            2010-12-08 22:57 | syx

            # re: 【數論內容】線性篩素數,線性篩歐拉函數,求前N個數的約數個數  回復  更多評論   

            26行寫錯了。。。應為e[i*prime[j]]=1;
            2011-08-25 14:58 | xyz
            亚洲香蕉网久久综合影视| 国产精品内射久久久久欢欢| 久久精品国产清自在天天线| 久久精品国产免费观看| 久久99精品久久只有精品| 国产福利电影一区二区三区久久老子无码午夜伦不 | 青青热久久国产久精品| 2020国产成人久久精品| 伊人久久大香线焦综合四虎| 久久精品综合网| 999久久久国产精品| 久久午夜电影网| 久久久国产精华液| 国产精品va久久久久久久| 一本久道久久综合狠狠爱| 久久国产成人午夜aⅴ影院| 三上悠亚久久精品| 一本大道久久东京热无码AV | 亚洲国产二区三区久久| 久久这里都是精品| 国内精品欧美久久精品| 亚洲国产精品18久久久久久| 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 国产亚洲精久久久久久无码| 久久成人18免费网站| 成人国内精品久久久久影院| 久久频这里精品99香蕉久| 久久电影网| 99久久精品免费看国产免费| 国产亚洲精品美女久久久| 日本欧美久久久久免费播放网| 久久人人爽人人精品视频| 久久精品国内一区二区三区| 久久综合九色综合网站| 伊人色综合九久久天天蜜桃| 久久人人爽人人精品视频| 国产精品99久久久久久www| 久久久精品一区二区三区| 91精品国产综合久久精品| 久久不见久久见免费视频7| 久久99精品国产麻豆宅宅|