歐拉篩
【算法簡介】
由於每個大於等於2的合數必定存在一個最小的質因數,所以只要篩去每個質數的倍數就相當於篩去了所有合數。但歐拉篩相比埃氏篩最大的優化就在於歐拉篩保證每個合數只被篩了一次,且是被其最小的質因數篩去的,所以歐拉篩的時間復雜度可以達到O(N)。
而如何保證每個合數都只被最小質因數篩去呢?讓我們先來看一看歐拉篩的實現(第一次用python寫博客,代碼習慣不太好請見諒):
1 n = input()
2 Del = [0] * (n + 1)
3 prime = []
4 for a in range(2,n + 1):
5 if Del[a] == 0:
6 prime.append(a)
7 for b in prime:
8 if a * b > n: break
9 Del[a * b] = 1
10 if a % b == 0: break
11 print prime
算法其他部分和埃氏篩思路類似,在此就不再贅述。而核心就在於這句
當a % b == 0時,b為a的一個質因子,所以a = K * b。令K = a / b,則用質數數組的接下來某個質數b'去篩a * b'的時候,a * b' == K * b * b',因而b和b'都是a * b'的質因子。由於b < b',故a * b'的最小質因數是b而不是b'。如果不break就會用非最小質因數b'篩完之后,再當a' == K * b'時用b又篩一遍,提高了復雜度。所以當a % b == 0時,后續的a * b'只需讓循環中接下來的某一個a' == (a / b) * b'時用b篩掉即可,既保證了每個數都被其最小質因數篩去,也保證了每個數都只被篩一次。
【利用歐拉篩求最小質因數】
根據【算法簡介】中的介紹,每個非質數都被其最小質因數篩去,所以只要在被篩去的時候記錄一下被哪個質數篩去,這樣就的到了最小質因數,相當於是歐拉篩的“副產品”。python實現如下:
n = input("")
Del = [0] * (n + 1)
Son = [0] * (n + 1)
prime = []
for a in range(2,n + 1):
if Del[a] == 0:
prime.append(a)
Son[a] = a
for b in prime:
if a * b > n: break
Del[a * b] = 1
Son[a * b] = b
if a % b == 0: break
print prime;
for a in range(2,n + 1):
print a,"->",Son[a];