1. 程式人生 > >PAT 1007. 素數對猜想 python 執行超時問題解決方案

PAT 1007. 素數對猜想 python 執行超時問題解決方案

原問題 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))  #繼續最優化迴圈上限
for 
prime 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,讓我們多動腦筋