1. 程式人生 > >【線性求質數】【最小質因數】淺析尤拉篩

【線性求質數】【最小質因數】淺析尤拉篩

尤拉篩

【演算法簡介】

  由於每個大於等於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

  演算法其他部分和埃氏篩思路類似,在此就不再贅述。而核心就在於這句

if a % b == 0: break

  當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];