Python入門習題(98)——OpenJudge百練習題:求10000以內n的階乘

OpenJudge百練第2731號習題:求10000以內n的階乘

題目描述

來源
OpenJudge網站 —— 百練習題集-第2731號習題

要求
總時間限制: 5000ms 內存限制: 655360kB

描述

求10000以內n的階乘。

輸入
只有一行輸入,整數n(0<=n<=10000)。
輸出
一行,即n!的值。
樣例輸入
100
樣例輸出

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

來源
JP06

解題思路

  1. 這一題的難點是:n很大時,n!的結果會大到無法用一個整數變量來存儲。解決辦法是用一個列表(即數組)來存儲作爲結果的整數的各個數位。

  2. 下面一節給出的代碼中,用n_digits列表存儲作爲結果的整數的各個數位。n_digits[0]是個位,[1]是十位,[2]是百位, …,依次類推。

  3. 假設n_digits存儲了(m-1)!的結果,那麼如何求m!呢?答案是,n_digits的各個數位分別乘以m。具體做法是:
    (1)令jinwei = 0。jinwei變量記住向前的進位。
    (2)個位乘以m。n_digits[0] = n_digits[0] * m + jinwei。進位jinwei = n_digits[0]除以10的商;新的個位n_digits[0] = n_digits[0]除以10的餘數。
    (3)十位乘以m,加上進位jinwei。n_digits[1] = n_digits[1] * m + jinwei。進位jinwei = n_digits[1]除以10的商;新的個位n_digits[1] = n_digits[1]除以10的餘數。
    (4)百位乘以m,加上進位jinwei。n_digits[2] = n_digits[2] * m + jinwei。進位jinwei = n_digits[2]除以10的商;新的個位n_digits[2] = n_digits[2]除以10的餘數。
    (5)…
    (6)依次類推,一直到(m-1)!的最高位。把最高位的進位記作jinwei。
    (7)如果jinwei > 0,那麼增設一位最高位,其值 = jinwei % 10。令jinwei = jinwei 除以10的商。
    (8)如果jinwei > 0,那麼增設一位最高位,其值 = jinwei % 10。令jinwei = jinwei 除以10的商。
    (9)…
    (10)重複上一步驟,直至jinwei等於0。

參考答案

# print("10!=", 10*9*8*7*6*5*4*3*2*1)
# print("15!=", 15*14*13*12*11*10*9*8*7*6*5*4*3*2*1)
from array import array
n_digits = array('L')  #n_digits[0]是個位,[1]是十位,[2]是百位, ...

#n_digits存儲了(m-1)!的結果,求出m!的結果
def times(n_digits, m):
    #各個數位乘以m
    jinwei = 0
    for i in range(len(n_digits)):
        n_digits[i] = n_digits[i] * m + jinwei
        jinwei = n_digits[i] // 10
        n_digits[i] = n_digits[i] % 10
    #最高位的進位目前可能是數十,數百,數千,...
    while jinwei > 0:
        n_digits.append(jinwei % 10)
        jinwei = jinwei // 10
    return n_digits

n = int(input())

if n <= 1:
    print(1)
else:
    n_digits.append(1) #1! = 1
    for i in range(2, n+1):
        n_digits = times(n_digits, i)
    for d in n_digits[len(n_digits)-1::-1]:
        print(d, end='')
    print()

測試用例

  1. 題目描述給出的測試用例,結果值比較大。要比對樣例輸出和程序輸出,可以把兩組數據複製到同一個編輯器窗口內,上下對齊,比對就容易了。

  2. 小一點的n。
    樣例輸入
    10
    樣例輸出
    3628800

  3. 另一個小一點的n。
    樣例輸入
    15
    樣例輸出
    1307674368000
    你應該能夠猜到上一節代碼中的前兩行的作用了。

  4. n=1。
    樣例輸入
    1
    樣例輸出
    1

小結

  1. 把“參考答案”一節的代碼提交到OpenJudge網站上後,反饋的結果是“ Time Limit Exceeded ”,意思是超時,用時超過了50000ms(即50秒)。採用同樣的算法,用C語言實現的代碼提交到OpenJudge網站上後,返回的結果是“Accepted”,用時2373ms。可見:(1)算法沒有問題。(2)Python的運行效率比較低。
  2. 有人把類似問題概括爲高精度整數類型的問題。這一類問題通常會生成一個巨大的數,大到無法用變量直接存儲的數。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章