【Python練習題 020】 求1+2!+3!+...+20!的和
--------------------------------------------------
據說這題是“累積累加”的問題,把“1+2!+3!+...+20!”展開就變成:
1
1*2
1*2*3
1*2*3*4
……
1*2*3*4……*20
弄懂了這規律,問題就好解決了。代碼如下:
sum = 0 x = 1 for i in range(1,21): x = x * i sum = sum + x print(sum)
輸出結果如下:
2561327494111820313
【2016-10-18 更新】------------------------------------------------
感謝 rm-rf 的指教,用遞歸、lambda、functools.reduce() 這三把斧頭為我們提供了新思路。不過,新知識太多了,一時我接受不了,還是一樣一樣來吧。
先不管遞歸,我們來看看使用了 lambda 和 functools.reduce() 的代碼吧:
import functools sum = 0 for i in range(1,21): sum = sum + functools.reduce(lambda x,y: x*y, range(1, i+1)) print(sum)
根據網上的資料,上述代碼中,lambda x,y: x*y 的意思是:有一個函數,接受x, y兩個參數做乘法。也就是說,把函數壓縮到1行,真是很簡潔。
而 functools.reduce() 也很神奇,大概結構是 functools.reduce(函數, 序列, 初始參數),其中括號里的函數需要2個參數,如果沒有指定初始參數,就先從序列中拿出2個傳遞給函數,之后把結果作為第1個參數,再從序列中拿出第3個項目作為第2個參數一起傳遞給函數,如此循環至序列空空為止。如果指定初始參數,則這個初始參數作為第1個參數,然后從序列中拿出1個作為第2個參數,傳遞給函數。請參見官方文檔。
上述代碼中,functools.reduce(lambda x,y: x*y, range(1,i+1)) 意思就是說:先從 range(1,i+1) 拿出2個元素,作為參數傳遞給乘法函數 lambda x,y: x*y,計算出的結果搖身變成參數,再從 range(1, i+1) 拿出1個元素,兩個配一起傳遞給函數重新計算。假如是 range(1, 4),這個函數就會計算 (1*2)*3。
有了以上做鋪墊,外面再套個 for 從1循環到20,就能得出題解。
弄明白 lambda 和 functools.reduce() 之后,就可以用遞歸來解決這道題了。
所謂“遞歸”,就是在函數體中調用自身。也就是說,在函數的計算式里,有一個元素是需要另外拿出來,放進這個函數里進行計算的,而在計算這個元素時,可能又有一個元素還得拿出來單獨再計算,直到所有元素都不符合條件,循環也就結束了。
就像本題,倒着寫就成了 20! + 19! + 18! + ... + 3! + 2! + 1。如果每個階乘 n! 都寫成 f(n),計算 f(n) 時需要先知道 f(n-1) 的結果,而計算 f(n-1) 時同樣又需要先計算 f(n-2) 的值,如此循環,直至 n == 1,遞歸結束 …… 我覺得我根本講不清楚!!不管了,上代碼:
import functools def f(n): if n == 1: return 1 else: return functools.reduce(lambda x,y: x*y, range(1, n+1)) + f(n-1) print(f(20))
唉,其實還是蠻難理解的。多做點練習,也許能逐漸掌握吧……
++++++++++++++++++++++++++++++++++++++