埃氏篩
簡單,暴力。
int isprime[50000];
void getlist(int size)
看似簡單,但不真搞明白這個,無法學會線性 ( 尤拉 ) 篩。
關鍵在於如何去做的合數,用了兩個引數,乙個是質數,即 prime[ i ] ,另乙個是質數的倍數,即 j 。相乘得到合數。
線性篩
埃氏篩的改良版,使乙個合數只被做出來一次。
模擬dfs的一些判重,用一定的順序( 如從小到大 )來去重。在這裡,我們便是保證每個合數只被最小的質因數做出來。
為什麼呢?
引用一段標準解釋:
prime 陣列中的素數是遞增的,當i能整除 prime[ j ],那麼 i*prime[ j+1 ]這個合數肯定被 prime[ j ] 乘以某個數篩掉。請看下面乙個樣例,假設我們的倍數遍歷到了9,而去乘它的質數到了3。因為i中含有 prime[ j ] , prime[ j ] 比 prime[ j+1 ]小,即 i = k*prime[ j ]。
那麼 i * prime[ j+1 ] = (k*prime[ j ]) * prime[ j+1 ] = k』 * prime[ j ],接下去的素數同理。所以不用篩下去了。
因此,在滿足 i%prime[ j ] == 0這個條件之前以及第一次滿足改條件時, prime[ j ] 必定是 prime[ j ] * i 的最小因子。
遍歷的倍數 9
質數表 2 3 5 7
這時候我們就可以換下乙個倍數10了,為什麼呢?
假如我們繼續,用9*5得到45,請注意,因為3是9的因數,所以3也是45的因數,且必定是45的最小質因數。因為3是9的最小質因數,除非9乘的質因數小於3,否則45的最小質因數就是3。5在3的右邊,所以winner就是3了。那麼15就是造這個合數所需要的倍數,肯定大於9,會在後面遍歷到這個倍數。
所以在3*9後,我們可以換下乙個倍數10了。
我將 i ,j 對換,來匹配埃氏篩的意義。
int isprime[50000], prime[10000], tot;
void getlist(int size)
} return;
}
還是得多去複習。 埃氏篩 尤拉篩
對於1 n範圍內素數的查詢,我們常用的二重迴圈暴力演算法的複雜度是o n2 如果利用開根縮小範圍的時間複雜度也無非是在o n nn sqrt n nn 而,這些演算法對於n在105以內都是可以接受的,但是如果需要更大範圍的素數表,這些演算法將顯得力不從心。下面將介紹更加高效的演算法。埃氏篩也叫素數篩...
素數篩法 埃氏篩及尤拉篩
在做題中會經常遇到有關素數的問題,整理一下學過的兩種素數篩法。時間複雜度 o nloglogn 我們知道乙個素數的倍數肯定是乙個合數,乙個合數可以由多個素數相乘得到,所以可以從2開始把2的倍數篩一遍,找到下個素數在篩一遍。篩完後素數的倍數都被篩掉了,剩下的就是素數。如下 const int n 1e...
線性篩法求素數(埃氏篩法 尤拉篩法)
篩法都是初始化把所有數都先設為素數,然後篩除合數。理解起來比較簡單,就是從小到大的列舉每乙個數,標記它的所有倍數都是合數 非素數 放到u i 為false,u中的下標對應的就是這個數的值。bool u maxn int num,su maxn 1.埃氏篩法 void prime 從小到大的篩選素數,...