相比於時間複雜度為 o(n(lgn)2) 的埃氏篩法,eular 質數篩法就顯得非常短小精悍。
尤拉篩的時間複雜度為 o(n),是一種空間換取時間的演算法。
一、空間需求
尤拉篩需要兩個陣列:
① prime,用來儲存素數。
② is_prime,用來表示 i (i <= n) 是否為質數。
二、步驟
① memset(is_prime, 1, sizeof(is_prime))
將 is_prime 陣列全部置為 1。
② 外層迴圈loop:for( i = 2 -> n)
遍歷每個數字 i 。
③ 若 i 為質數,那麼將 i 加入 prime 陣列。
④ 內層迴圈loop:for(j = 0 -> prime.length)
不論 i 是否為質數都會進入內層迴圈。
⑤ 若 i * prime[j] > n 則 break 內層迴圈loop。
否則,is_prime[ i * prime[j] ] = 0
把 i * prime[j] 標記為合數。
⑥若 i % prime[j] == 0 則 break 內層迴圈loop,繼續外層迴圈loop。
三、核心
尤拉篩效率這麼高的核心就在於上面的第⑥點,
若 i % prime[j] == 0 則退出內層迴圈loop。
為什麼可以直接退出呢?後面的數就不用繼續篩選了嗎?
是的,當 i % prime[j] == 0 時,說明i = prime[j] * k
對於 prime[j] 後面的元素 prime[next_j],
prime[next_j] * i 將會在之後的篩選中被篩掉,無需重複。
因為prime[next_j] * i = prime[next_j] * (prime[j] * k)
= prime[j] * (prime[next_j] * k)
例如:prime = i = 4
2*4 = 8 被篩 此時 4%2 == 0 break
3*4 = 12 這次不篩
因為 4 = 22, 故 3 * (22) = 2 * (3*2)
在 3 * 2 = 6 = i 時會篩掉12。
int
*prime;
int*is_prime;
void
getprime
(int n)
int cnt =0;
for(
int i =
2; i <= n; i++
)for
(int j =
0; j < cnt; j++
) is_prime[prime[j]
*i]=0;
if(i%prime[j]==0
)}}}
【end】感謝** Eular質數篩法
任意乙個正整數k,若k 2,則k可以表示成若干個質數相乘的形式。eratosthenes篩法中,在列舉k的每乙個質因子時,我們都計算了一次k,從而造成了冗餘。因此在改進演算法中,只利用k的最小質因子去計算一次k。而在其基礎上改進的eular篩法,其偽 為 isprime true primelist...
數論二 Eular質數篩法
如何去快速得求解 1,n 這個區間內素數的個數呢?自然我們已經知道了如何快速判定乙個數是否是質數,那麼我就直接將 1,n 之間每乙個數判定一次,就可以得到結果。雖然我們已經通過快速素數檢測將每一次判定的時間複雜度降低,但是n個數字的話,總的時間複雜度依舊很高。發現如果乙個數p是質數的話,那麼它的倍數...
數論二 Eular質數篩法
時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述小ho 小hi,上次我學會了如何檢測乙個數是否是質數。於是我又有了乙個新的問題,我如何去快速得求解 1,n 這個區間內素數的個數呢?小hi 你自己有什麼想法麼?小ho 有!我一開始的想法是,自然我們已經知道了如何快速判定乙...