信息学奥赛一本通 2040:【例5.7】筛选法找质数 (普通筛 线性筛)
【題目鏈接】
ybt 2040:【例5.7】篩選法找質(zhì)數(shù)
【題目考點】
1. 普通篩法找質(zhì)數(shù)(埃拉托色尼篩法)
基本思想:把從2到N的一組正整數(shù)從小到大按順序排列。從中依次刪除2的倍數(shù)、3的倍數(shù)、5的倍數(shù),直到N\sqrt{N}N?的倍數(shù)為止,剩余的即為2~N之間的所有質(zhì)數(shù)。
普通篩法復(fù)雜度為:O(nloglogn)O(nloglogn)O(nloglogn)
為什么直到N\sqrt{N}N?的倍數(shù)為止,以下是證明:
- 命題:對于整數(shù)n滿足N<n≤N\sqrt{N} < n \le NN?<n≤N,n是質(zhì)數(shù),或n是合數(shù)時,存在一個整數(shù)a滿足a≤Na \le \sqrt{N}a≤N?,a是n的因數(shù)。
- 證明:顯然n可以是質(zhì)數(shù)。如果n是合數(shù),使用反證法。
- 假設(shè)n是合數(shù)時,n的因數(shù)(除了1)都大于N\sqrt{N}N?。由于n是合數(shù),n至少有兩個不為1或n的因數(shù),設(shè)為a,b,且存在等式a?b?x=na\cdot b\cdot x = na?b?x=n,其中x是某個正整數(shù)。
有a>N,b>N?a?b>N≥na>\sqrt{N}, b>\sqrt{N} \Rightarrow a\cdot b >N\ge na>N?,b>N??a?b>N≥n,即a?b>na\cdot b > na?b>n
根據(jù)a?b?x=na\cdot b\cdot x = na?b?x=n,有a?b≤na\cdot b \le na?b≤n
出現(xiàn)矛盾,因而假設(shè)不成立,原命題得證。
2. 線性篩(歐拉篩)
基本思想:讓每個合數(shù)只通過它最小的質(zhì)因數(shù)被篩掉。
例:
8的最小質(zhì)因數(shù)是2,那么讓合數(shù)8通過質(zhì)數(shù)2被篩掉。
15的最小質(zhì)因數(shù)是3,那么讓合數(shù)15通過質(zhì)數(shù)3被篩掉。
普通篩法中,數(shù)字可能會被多次篩掉,線性篩中,每個數(shù)字只被篩掉一次。
線性篩法復(fù)雜度為:O(n)O(n)O(n)
線性篩的字面意思就是該算法的復(fù)雜度為線性的。
例:對于合數(shù)15
在普通篩法中:看質(zhì)數(shù)3的倍數(shù)時,15被篩掉一次,看質(zhì)數(shù)5的倍數(shù)時,15被篩掉一次。
在線性篩中: 15只會通過質(zhì)數(shù)3被篩掉一次。
線性篩法中,維護一個質(zhì)數(shù)數(shù)組prime[]。
算法如下:
- 每次循環(huán)觀察一個數(shù)字i
- 如果i是質(zhì)數(shù),加入質(zhì)數(shù)數(shù)組
- 無論i是不是質(zhì)數(shù),都順序遍歷質(zhì)數(shù)數(shù)組,取到的質(zhì)數(shù)為prime[j]
- 只要i不是prime[j]的倍數(shù),那么prime[j]就是i*prime[j]的最小質(zhì)因數(shù)。i*prime[j]這個合數(shù)通過prime[j]這個最小質(zhì)因數(shù)被篩掉了。
- 如果i是prime[j]的倍數(shù),則跳出循環(huán)
原理解釋如下:
- 由于prime數(shù)組中的質(zhì)數(shù)是遞增的,在遍歷prime數(shù)組的過程中,只要沒有遇到i是prime[j]的倍數(shù)的情況,那么prime[j]一定是i*prime[j]的最小質(zhì)因數(shù)。當(dāng)?shù)谝淮斡龅絠是prime[j]的倍數(shù)的情況時,prime[j]仍然是i*prime[j]的最小質(zhì)因數(shù)。
- 如果繼續(xù)看prime[j]后面第x個質(zhì)數(shù)(x大于等于1),此時要判斷數(shù)字Y=i*prime[j+x]是否要被篩掉。由于prime[j+x] > prime[j],i已經(jīng)具有更小的質(zhì)因數(shù)prime[j],所以數(shù)字Y的最小質(zhì)因數(shù)是prime[j]而不是prime[j+x],所以Y這個數(shù)不應(yīng)該在i為這個值時被篩掉,它應(yīng)該在i為Y/prime[j]時被篩掉。
例:假設(shè)i是25。25不是2的倍數(shù),那么2是2*25的最小質(zhì)因數(shù),25也不是3的倍數(shù),那么3是3*25的最小質(zhì)因數(shù),25是5的倍數(shù),5仍然是5*25的最小質(zhì)因數(shù)。
25不是7的倍數(shù),7不是7*25的最小質(zhì)因數(shù)了。7*25=175被篩掉的時機是:當(dāng)i循環(huán)到35時,175=35*5,5是175的最小質(zhì)因數(shù),175通過質(zhì)數(shù)5被篩掉。
【題解代碼】
解法1:普通篩法(埃拉托色尼篩法)
#include<bits/stdc++.h> using namespace std; int main() {bool isPrime[1005] = {};//isPrime[i]:i是否是質(zhì)數(shù) int n;cin >> n;for(int i = 2; i <= n; ++i)//初值狀態(tài)下,把每個數(shù)字都標(biāo)記為質(zhì)數(shù) isPrime[i] = true;//isPrime[0],與isPrime[1]都為false,0,1都不是質(zhì)數(shù) for(int i = 2; i <= int(sqrt(n)); ++i){if(isPrime[i]){for(int j = 2*i; j <= n; j += i)//如果一個數(shù)字是某質(zhì)數(shù)的倍數(shù),那么把它標(biāo)記為合數(shù) isPrime[j] = false;}}for(int i = 2; i <= n; ++i){if(isPrime[i])cout << i << endl;}return 0; }解法2:線性篩(歐拉篩)
#include<bits/stdc++.h> using namespace std; int main() {bool isPrime[1005] = {};//isPrime[i]:i是否是質(zhì)數(shù) int n, prime[1005], psize = 0;//prime:質(zhì)數(shù)數(shù)組 psize:prime數(shù)組長度 cin >> n;for(int i = 2; i <= n; ++i)//初值狀態(tài)下,把每個數(shù)字都標(biāo)記為質(zhì)數(shù) isPrime[i] = true;//isPrime[0],與isPrime[1]都為false,0,1都不是質(zhì)數(shù) for(int i = 2; i <= n; ++i){if(isPrime[i])//如果i是質(zhì)數(shù) prime[++psize] = i;//將i填充到指數(shù)數(shù)組prime for(int j = 1; j <= psize && i*prime[j] <= n; ++j)//遍歷質(zhì)數(shù)數(shù)組 {//篩去當(dāng)前觀察的數(shù)i與某質(zhì)數(shù)prime[j]的乘積isPrime[i*prime[j]] = false;//i*prime[j]這個數(shù)通過prime[j]篩掉 if(i%prime[j] == 0)break;}}for(int i = 2; i <= n; ++i){if(isPrime[i])cout << i << endl;}return 0; }總結(jié)
以上是生活随笔為你收集整理的信息学奥赛一本通 2040:【例5.7】筛选法找质数 (普通筛 线性筛)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java输出华氏摄氏温度转换表_Pyth
- 下一篇: matlab在常微分方程的应用,MATL