PAT 1007. 素數對猜想 python 執行超時問題解決方案
阿新 • • 發佈:2019-01-01
原問題 https://www.patest.cn/contests/pat-b-practise/1007
讓我們定義 dn 為:dn = pn+1 - pn,其中 pi 是第i個素數。顯然有 d1=1 且對於n>1有 dn 是偶數。“素數對猜想”認為“存在無窮多對相鄰且差為2的素數”。
現給定任意正整數N (< 105),請計算不超過N的滿足猜想的素數對的個數。
輸入格式:每個測試輸入包含1個測試用例,給出正整數N。
輸出格式:每個測試用例的輸出佔一行,不超過N的滿足猜想的素數對的個數。
輸入樣例:20輸出樣例:
4思路非常簡單,一個函式判斷某個數是否為質數,主函式從5迴圈到正整數N即可,關鍵問題在於判斷質數的函式效率如何
以下從低到高說幾種質數判斷方法(number為待判定的數):
LEVEL 0.
up_limit = number #以number本身作為迴圈上限
foriin range(2, up_limit):#嘗試從2到number-1的每一個數是否可以被number整除
if number % i== 0:#餘數為零則不是素數 return False return True
LEVEL 0.5.
up_limit = int(number/2) #不用多說吧,最小的除數是2,不可能有大於 number/2 的約數的,順便取整
LEVEL 1.
import math
up_limit = math.sqrt(number) #從上一級容易想到,約數都是兩兩一對的,只需要嘗試當中一半即可;最合理的是嘗試小於其平方根的每個值
LEVEL 2.
然而,壞訊息是即使使用了平方根作為嘗試上限,PAT還是會返回 執行超時,自己試試 N=99999 也會發現時間挺長
優化資料上限的路已經走到頭,只能考慮在除數上進行刪減篩除,考慮如下問題:
如果一個數 C 能被 (a*b) 整除,那麼 C%a 或者 C%b 是多少?
顯然,餘數都是零,也就是說一個數肯定能被它的約數的約數整除
因此,一切合數作為被除數都是重複勞動
綜上,只需要嘗試一個數能否被小於它的平方根的素數整除
此時可以建立一個素數的陣列,被除數只在這個陣列中嘗試,示例程式碼如下:
up_data = int(math.sqrt(number)) #繼續最優化迴圈上限 forprime in primes: #只嘗試素數作為被除數 if prime > up_data: #迴圈上限的控制 break if number % prime == 0: return False return True
該問題全部程式碼如下:
import math def is_prime(number, primes): up_data = int(math.sqrt(number)) for prime in primes: if prime > up_data: break if number % prime == 0: return False return True up_limit = input() up_limit = int(up_limit) last_prime, next_prime = 2, 3 count = 0 primes = [2, 3] if up_limit > 4: for number in range(5, up_limit+1): if is_prime(number, primes): primes.append(number) last_prime = next_prime next_prime = number if (next_prime - last_prime) == 2: count += 1 print(str(count))現在,恭喜獲得PAT 乙級 1007問題 最後的2分
據說使用C語言只需要LEVEL 1.5的優化即可通過,畢竟兩種語言的效率不可比
然而,感謝python,讓我們多動腦筋