python之尋找第n個默尼森數

1.貼題

題目來自MOOC
《用Python玩轉數據》(南京大學)
第二週編程作業


尋找第n個默尼森數。
代碼格式如下:
def prime(num):

def monisen(no):
… …
return xxx

print(monisen(int(input()))) #此處不需要自己輸入,只要寫這樣一條語句即可,主要完成monisen()函數(4分)
經典程序設計問題:找第n個默尼森數。P是素數且M也是素數,並且滿足等式M=2**P-1,則稱M爲默尼森數。例如,P=5,M=2**P-1=31,5和31都是素數,因此31是默尼森數。
輸入格式:按提示用input()函數輸入
輸出格式:int類型
輸入樣例:4
輸出樣例:127

時間限制:500ms內存限制:32000kb


2.說明

題目還給出了格式,降低了難度。主要思路是通過定義兩個函數,其中第一個函數用來判斷是不是素數,第二個函數用來判斷是不是默尼森數並控制輸出第幾個默尼森數。

首先是判斷是不是素數的函數,這個函數也是初學者必然要進行練手的。思路爲從2開始(因爲判斷能不能被1整除沒有意義)到它本身減一,是否沒有數可以被整除,如果沒有的話就是素數,否則不是。而通過數學知識可以知道上界可以降低到它本身的平方根,因爲如果一個數如果可以分解爲兩個數的因子,那麼它的因子的小的那一個一定會小於或等於它的平方根。因爲一個數的平方根可以不是整數,所以一般的做法是將平方根取整數部分然後加一作爲上界。

判斷是不是默尼森數在本次代碼中使用了逐個加一的方式,屬於笨辦法。

3.參考代碼

import math #要用到平方根的函數,所以要導入math庫
def prime(num): #判斷是否爲素數的函數,返回真或假代表是素數或不是素數
    flag = True #首先預置flag爲真
    for i in range(2,int(math.sqrt(num))+1): #從2到平方根取整加一的循環
        if num%i == 0: #判斷是否整除
            flag = False #如果整除則將flag改爲假
            return flag #返回flag爲假,結束函數
    return flag #如果找不到整除的數,則範圍flag爲真,結束函數


def monisen(no): #判斷是不是默尼森數並控制輸出第幾個默尼森數
    p = 5 #p從5開始,因爲判斷素數的函數採用了平方根取整加一的上界,不可以對4及以下的數進行判斷,否則會報錯
    if no == 1: #手動分支第一個和第二個默尼森數
        return 3
    elif no == 2:
        return 7
    else:
        while no>2:  #經過手動驗證p=2,m=3;p=3,m=7是第一和第二個默尼森數,因此循環次數要減少兩次
            if prime(p): #判斷p是否爲素數
                m = 2 ** p -1 #根據公式計算m
                if prime(m): #判斷m是否爲素數
                    no -= 1 #如果m爲素數,則說明找到一個默尼森數,no減一
            p += 1 #p加一準備進入下一個循環
        return  m #返回第no個默尼森數

print(monisen(int(input()))) #執行函數

4.後記

寫完代碼和說明後又去網上查了人家寫的代碼,大概看了看思路都是大同小異,有的大神采用緩存保存素數來着,過程太複雜了等以後再研究。

學到了一個導入時間庫看程序運行時間的,碼!

import time
#中間是我的源代碼,與上面的參考代碼相同
import math
def prime(num):
    flag = True
    for i in range(2,int(math.sqrt(num))+1):
        if num%i == 0:
            flag = False
            return flag
    return flag


def monisen(no):
    p = 5
    if no == 1:
        return 3
    elif no == 2:
        return 7
    else:
        while no>2: 
            if prime(p):
                m = 2 ** p -1
                if prime(m):
                    no -= 1
            p += 1
        return  m
#函數定義結束

start = time.clock()
print(monisen(int(input()))) 
end = time.clock()
print("time: %f s" % (end - start))

當輸入爲8時,輸出結果爲

2147483647
time: 0.005812 s

5.疑問

在判斷是否是默尼森數是,判斷完p後判斷下一個p時,採用了加一的方法,不知道是否有相關的數學證明可以減少判斷次數,即增加步長。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章