厄拉多塞篩法

2022-09-06 01:57:09 字數 1764 閱讀 9638

厄拉多塞篩演算法(eratosthenes sieve)是一種求素數的方法,由古希臘數學家厄拉多塞提出。它的原理是,給定乙個數 n,從 2 開始依次將 \(\sqrt\) 以內的素數的倍數標記為合數,標記完成後,剩餘未被標記的數為素數(從 2 開始)。如此可省去檢查每個數的步驟,使篩選素數的過程更加簡單。厄拉多塞篩演算法具體步驟如下:

讀取輸入的數 n,將 2 到 n 的所有整數記錄在表中

從 2 開始,劃去表中所有 2 的倍數

由小到大尋找表中下乙個未被劃去的整數,再劃去表中所有該整數的倍數

重複第(3)步,直到找到的整數大於 \(\sqrt\) 為止

表中所有未被劃去的整數均為素數

"""厄拉托塞篩法"""

if n < 2: # 不存在小於 2 的素數

return

is_prime = [true for _ in range(n + 1)]

# 遍歷 i=2 到 根號 n

for i in range(2, int(pow(n, 0.5)) + 1):

if is_prime[i]: # 篩去 i 的倍數

for j in range(i * i, n + 1, i):

is_prime[j] = false

# 返回 2 到 n 中未被篩去的數

return [i for i in range(2, n + 1) if is_prime[i]]

在篩去 i 的倍數的時候,第乙個數是 \(i \times i\) 而不是 i,這是因為對於所有 \(k \times i , \; k < i\),都在前面被篩過,故可以跳過這些數

這個演算法很大的乙個問題是對空間很不友好,需要儲存很大的乙個素數表

除了 2 之外,所有的素數都是奇數,那麼在篩的時候只需要考慮奇數即可

在構建**的時候,先前將下標 i 對應整數 i,現在可以將下標 i 對應整數 2i+3,節約一半的儲存空間

def sieve_prime(n: int) -> list:

"""厄拉托塞篩法"""

if n < 2: # 不存在小於 2 的素數

return

elif n == 2:

return [2]

end = (n - 3) // 2

is_prime = [true for _ in range(end + 1)]

# 遍歷 i=3 到 根號 n

for i in range(3, int(pow(n, 0.5)) + 1, 2):

k = (i - 3) // 2 # 將 i 對映回下標 k

if is_prime[k]: # 篩去 i 的倍數

for j in range(i * i, n + 1, 2 * i):

is_prime[(j - 3) // 2] = false

# 返回 2 到 n 中未被篩去的數

return [2] + [2 * i + 3 for i in range(end + 1) if is_prime[i]]

除了厄拉多塞篩法之外,還有尤拉篩等篩法

使用 python 時間和空間效率都較低,對於標記素數,可以採用 c++ 的 bitset,bitset 是以位元為單位標記的,會極大降低儲存消耗

厄拉多塞篩法

簡介 1 厄拉多塞篩法 簡介 西元前250年,希臘數學家厄拉多塞 eeatosthese 想到了乙個非常美妙的質數篩法,減少了逐一檢查每個數的的步驟,可以比較簡單的從一大堆數字之中,篩選出質數來,這方法被稱作厄拉多塞篩法 sieve of eeatosthese 具體操作 先將 2 n 的各個數放入...

LeetCode 計數質數(厄拉多塞篩法)

2020年5月27日 解題 質數寫法的固化思維使人第一想法就寫出下面的 厄拉多塞篩法通過質數推算出接下來的非質數,一直算到n。舉個例子 質數2,我們可以推算出2x2 4 2x3 6 2x4 8等,能發現質數的倍數都是非質數,標記下來 接下來到質數3,我們可以推算出3x2 6 3x3 9 3x4 12...

求素數(厄拉多塞篩法 暴力列舉法)

首先 找出第乙個素數,把他的倍數賦值為0 其次 找出其後第乙個不為0的數,該數為素數,把他的倍數賦值為0 最後 重複上述步驟.篩選法也叫厄拉多塞篩法,因為素數的倍數必然不是素數,所以把素數的倍數全置為0,用乙個新的陣列儲存那些不為0 的數,即為素數 include include void putp...