演算法中有一類題,題目中涉及到大量素數的判定,只要範圍確定,素數的個數和素數就已經是固定不變的,那麼我們可以考慮先預處理,把範圍內所有素數篩選出來,那麼篩素數的方法有哪些,下面就兩種演算法的思想和標程進行說明。
一、埃氏(eratosthenes)篩素數。
原理:基於任意整數x的倍數2x,3x,4x,...都不是質數。時間複雜度為o(nlog logn),該演算法原理比較好理解,演算法競賽中常用此演算法篩質數。
我們可以從2開始,從小到大掃瞄每個數x,把x的倍數x*2,x*3,...x*(n/x)標記為非質數【此處其實可以優化,不用從2倍開始,因為對於每個數x,x的2倍,3倍都會被2,3,..】。當掃瞄到乙個數x時,若未被標記為非質數,那麼該數便是質數,因為它能在比它小的數的過篩過程中逃過,就說明它前面沒有乙個數是它的倍數,然乙個數的因子只可能比它小,因此我們可以斷定,該數x便是乙個素數。
標程如下:
bool isprime[10000005];
void aishiprime(int n)
}
}
二、線性篩法
核心原理:對於每個合數,都只由它最小的質因子篩掉。
比如:(假定:ans陣列中存放著已經確定的素數)
合數 i = p(最小素因子)* a;
若 i%ans[j] ==0; 則 i * ans[j+1] = p * a * ans[j+1] 可以被後面的 a * ans[j+1] 再乘以素數 p 篩選出來,(顯而p舉例如下【讀者自行模擬23以後的數的篩選過程】:
更正:上圖中i=20時,篩掉的素數是40.
標程如下:
const int maxn = 20000000;
bool isprime[maxn+1];
int ans[maxn/10] ,cnt;
void _prime(int n)
for(int j=1;j <= cnt && i*ans[j]<=n ; j++)
}
}
素數篩法(埃氏篩,線性篩)
時間複雜度o nloglogn void prime int b prime i 1則是合數 原理很簡單,所有合數可以表示為乙個質數跟另乙個數的積,列舉每個已知素數的倍數就能標記完。但很明顯,這樣做會有重複。比如12 3 4 2 6,在2這個素數進行倍數標記時會標記,在3這個素數進行倍數標記時同樣會...
線性篩法求素數(埃氏篩法 尤拉篩法)
篩法都是初始化把所有數都先設為素數,然後篩除合數。理解起來比較簡單,就是從小到大的列舉每乙個數,標記它的所有倍數都是合數 非素數 放到u i 為false,u中的下標對應的就是這個數的值。bool u maxn int num,su maxn 1.埃氏篩法 void prime 從小到大的篩選素數,...
埃氏篩法 素數篩
埃式篩法 給定乙個正整數n n 10 6 問n以內有多少個素數?做法 做法其實很簡單,首先將2到n範圍內的整數寫下來,其中2是最小的素數。將表中所有的2的倍數劃去,表中剩下的最小的數字就是3,他不能被更小的數整除,所以3是素數。再將表中所有的3的倍數劃去 以此類推,如果表中剩餘的最小的數是m,那麼m...