線性篩法

來源:互聯網
上載者:User

標籤:prim   質數   cpp   分解   遍曆   code   重複   線性篩   因子   

線性篩法

上節課講的是 Eratosthenes 篩法利用的原理是 任意整數 x 的倍數 2x,3x,... 等都不是質數

但是即便如此也會有重複標記的現象,例如12既會被2又會被3標記,在標記2的倍數時,\(12 = 6*2\),在標記3的倍數時,\(12 = 4*3\) ,根本原因是沒有找到唯一產生12的方式。

線性篩法的核心原理

每個合數必有一個最大因子(不包括它本身),用這個因子把合數篩掉

換言之:每個合數必有一個最小素因子,用這個因數把合數篩掉

過程

假設 i 是合數 t 的最大因數,t顯然可能不唯一(例如 30 和 45 最大因數都是 15)。但是仔細想一想,必然有

t = i * p(p為小於 i 的質數)

  • p為什麼比 i 小?因為 i 是 t 的最大因數。
  • 為什麼 p 一定是質數?因為如果 p 是合數,那麼 i 就一定不是 t 的最大因數,因為 p 可以再拆成若干素數相乘,這些素數再與 i 相乘會使因數更大。

既然如此,我們只需要把所有小於 i 的質數 p 都挨個乘一次好了。

真相真的是這樣的嘛?

其實不是的,一不小心就忘記了最初的條件。我們要滿足 i 是 t 的最大因數。如果 p 大於 i 的最小質因數,那 i 還是 t 的最大因數嘛?顯然不是,任何一個合數都能唯一分解為有限個質數的乘積,除去這其中最小的質因數,其他的都乘起來就是最大因數 i 。所以我們不能讓 p 大於 i 的最小質因數。

  • v[i] 表示 i 的最小質因數。規定如果為 1,v就是質數。
  • prime[j] 表示第 j 個質數。與之前的篩法不同,這個數組是存放質數的,而不是標記質數的
#define MAXN 1000000int prime[MAXN],v[MAXN];int m=0;//m表示現在篩出m個質數void primes(){    v[1] = 0;    for(int i=2;i<MAXN;i++)    {        if(v[i]==0)//如果v[i]為0,說明 i 之前沒有被篩到過,i 為質數        {            v[i] = 1;             prime[++m] = i;        }        for(int j = 1;j<=m;j++)//遍曆小於 i 的所有質數        {            //如果質數大於 i 的最小質因數或者乘起來大於MAXN就跳出迴圈            if(prime[j] > v[i] || prime[j] > MAXN/i)                 break;            v[i*prime[j]] = prime[j];//標記 i*prime[j] 的最小質因數是prime[j]        }    }}

線性篩法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.