[英]Prime numbers which can be written as sum of the squares of two numbers x and y
問題是:
給定一個數字范圍(x,y)
,找到所有質數(僅Count),它們是兩個數字的平方和,且限制為0<=x<y<=2*(10^8)
根據費馬定理 :
Fermat's theorem on sums of two squares asserts that an odd prime number p can be
expressed as p = x^2 + y^2 with integer x and y if and only if p is congruent to
1 (mod4).
我做了這樣的事情:
import math
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
return all(n % i for i in range(3, int(math.sqrt(n)) + 1, 2))
a,b=map(int,raw_input().split())
count=0
for i in range(a,b+1):
if(is_prime(i) and (i-1)%4==0):
count+=1
print(count)
但這在某些情況下會增加時間復雜度和內存限制 。
這是我的提交結果:
誰能通過更好的算法幫助我降低時間復雜度和內存限制 ?
問題鏈接 (不是正在進行的比賽,僅供參考)
不要檢查每個數字是否為質數。 使用Eratosthenes的Sieve預先計算范圍內的所有質數。 這將大大降低復雜度。
由於最多有200M個數字和256Mb的內存限制,並且每個數字至少需要4個字節,因此需要一點技巧。 不要用最多y
所有數字初始化篩子,而不要用不能被2、3和5整除的數字初始化篩子。這將減小篩子的初始大小,以適合內存限制。
UPD正如威爾·尼斯(Will Ness)在評論中正確指出的那樣,篩子僅包含標志,而不包含數字,因此每個元素需要不超過1個字節,並且您甚至不需要這種預先計算的技巧。
您可以通過將for i in range(a,b+1):
中for i in xrange(a,b+1):
更改for i in xrange(a,b+1):
for i in range(a,b+1):
來減少內存使用,以免在內存中不生成整個列表。
您可以在下面的語句中執行相同的操作,但是很正確,因為這樣做無助於時間。
return all(n % i for i in xrange(3, int(math.sqrt(n)) + 1, 2))
在內存方面可能不會比在另一個答案上花費那么多的一次優化是使用Fermat的Little定理 。 它可以幫助您及早拒絕許多候選人。 更具體地說,您可以選擇3或4個隨機值進行測試,如果其中一個拒絕,則可以拒絕。 否則,您可以進行當前正在執行的測試。
首先,盡管它不會改變時間復雜度的順序 ,但是您仍然可以將要檢查的數字列表縮小6倍,因為您只需要檢查等於1 mod 12
或等於5 mod 12
(例如[1,5],[13,17],[25,29],[37,41]等)。
由於您只需要計算素數(即兩個數字的平方和),因此順序無關緊要。 因此,您可以將range(a,b+1)
更改為range(1,b+1,12)+range(5,b+1,12)
。
顯然,您可以在函數is_prime
刪除if n % 2 == 0 and n > 2
條件,此外,將if is_prime(i) and (i-1)%4 == 0
條件更改為if is_prime(i)
。
最后,可以通過將它僅與相鄰的6的倍數(例如[5,7],[11,13],[17,19]號碼檢查每個數的素性,[23,25]等)。
因此,您可以更改此設置:
range(3,int(math.sqrt(n))+1,2)
對此:
range(5,math.sqrt(n))+1,6)+range(7,math.sqrt(n))+1,6)
您math.sqrt(n))+1
事先計算math.sqrt(n))+1
。
總結一下,這是提高程序整體性能的方法:
import math
def is_prime(n):
max = int(math.sqrt(n))+1
return all(n % i for i in range(5,max,6)+range(7,max,6))
count = 0
b = int(raw_input())
for i in range(1,b+1,12)+range(5,b+1,12):
if is_prime(i):
count += 1
print count
請注意,通常不會將1
視為質數,因此您可能需要打印count-1
。 另一方面, 2
不等於1 mod 4
,但是它是兩個平方的和,因此您可以按原樣保留它...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.