• <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 閱讀(3774) 評論(11)  編輯 收藏 引用

            評論

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

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

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

            線性的,復雜度在信息學競賽中已經相當優化了。~@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久久九九精品无码| 久久免费高清视频| 欧美黑人又粗又大久久久| 久久精品一区二区三区AV| 无码国内精品久久人妻蜜桃| 久久人人添人人爽添人人片牛牛| 久久丫忘忧草产品| 国产亚洲婷婷香蕉久久精品| 久久国产精品波多野结衣AV | 久久99精品国产麻豆宅宅| 国产 亚洲 欧美 另类 久久| 欧美成a人片免费看久久| 欧美一区二区三区久久综合| 久久播电影网| 国产亚洲美女精品久久久久狼| 久久久青草青青国产亚洲免观| 午夜精品久久久久久久久| segui久久国产精品| 欧美黑人又粗又大久久久| 精品伊人久久久| 国产高清国内精品福利99久久| 久久精品免费全国观看国产| 99久久精品国产一区二区| 成人久久免费网站| 久久中文字幕无码专区 | 777久久精品一区二区三区无码| 一本色道久久综合狠狠躁篇| 久久国产精品久久久| 午夜精品久久久久久久久| 精品伊人久久久| 久久久久亚洲AV无码观看| 一97日本道伊人久久综合影院| 久久九九久精品国产| 一本久久a久久精品综合夜夜 | 精品久久久久成人码免费动漫 | 久久综合久久伊人| 国产精品午夜久久| 久久精品视屏| 久久夜色精品国产亚洲av| 久久91精品综合国产首页| 久久亚洲精品无码观看不卡|