問題描述很簡單:求解n階乘的尾隨零個數
而所謂尾隨零個數,即是從個位數開始,數字連續為0的個數.
譬如:
3!(階乘符號,下同) = 3 * 2 * 1 = 6, 尾隨零個數為0
5! = 5 * 4 * 3 * 2 * 1 = 120, 尾隨零個數為1
10! = 10 * 9 * … * 1 = 3628800, 尾隨零個數為2
ok,明白問題之後,我們就來嘗試算一算吧~
方法1既然要求解階乘值的尾隨零個數,直觀的方法就是首先算出階乘值,然後對10取模來計算尾隨零個數,**如下:
function
factorial(n)
local val = 1
for i = 2, n do
val = val * i
endreturn val
endfunction
trailing_zero_count(value)
local count = 0
while
value % 10 == 0
do count = count + 1
value = value / 10
end return count
endfunction
factorial_trailing_zero_count(n)
local
value = factorial(n)
return trailing_zero_count(value)
end
方法2
方法1簡單直觀,但是當所求n階乘較大時容易造成乘法溢位(譬如n=40),一種方法是使用大數運算來解決溢位問題;另外一種更輕量的方法則是直接從尾數零的性質入手:
考慮一下,乙個數字a如果有乙個尾數零,其實就是意味著a有乙個10因子,如果有兩個尾數零,則說明a有兩個10因子(即有乙個 10 * 10 = 100 因子),以此類推~
所以我們只要知道了n階乘有多少個10因子就知道了n階乘有多少個尾數零,這裡我們不能直接計算n階乘的大小(還記的之前那個溢位問題嗎),而是要通過n階乘的定義(或者其他方式)來直接計算~
這裡我們需要一點技巧:
首先我們對10進行一下素數分解
10 = 2 * 5而
n! = n * (n - 1) * (n - 2) * … * 1
假設我們能求出某個數字a中2因子的個數,求解的方法設為
factor_2_count(a)
相似的,我們設求解某個數b中5因子的個數方法為
factor_5_count(b)
那麼有:
factor_2_count(n!) = factor_2_count(n) + factor_2_count(n - 1) + factor_2_count(n - 2) + … + factor_2_count(1)
factor_5_count(n!) = factor_5_count(n) + factor_5_count(n - 1) + factor_5_count(n - 2) + … + factor_5_count(1)
又由於10 = 2 * 5(乙個2因子和乙個5因子構成乙個10因子)
所以n!的10因子個數(即尾數零個數)為:
min(factor_2_count(n!), factor_5_count(n!))(min為最小值函式)
相關**如下:
function
factor_2_count(n)
local count = 0
while n % 2 == 0
do count = count + 1
n = n / 2
end return count
endfunction
factorial_factor_2_count(n)
local count = 0
for i = 1, n do
count = count + factor_2_count(i)
endreturn count
endfunction
factor_5_count(n)
local count = 0
while n % 5 == 0
do count = count + 1
n = n / 5
end return count
endfunction
factorial_factor_5_count(n)
local count = 0
for i = 1, n do
count = count + factor_5_count(i)
endreturn count
endfunction
factorial_trailing_zero_count_v2(n)
return math.min(factorial_factor_2_count(n), factorial_factor_5_count(n))
end
方法3
考慮方法2的解法步驟,我們分別計算了n階乘中因子2的個數和因子5的個數,但實際上,n階乘中因子2的個數一定是大於等於因子5的個數的(數學歸納法應該是證明的一種方法),即:
factor_2_count(n!) >= factor_5_count(n!)
所以有:
min(factor_2_count(n!), factor_5_count(n!)) = factor_5_count(n!)
這也意味著實際上我們只需要計算n階乘中因子5的個數就可以了~
**如下:
function
factor_5_count(n)
local count = 0
while n % 5 == 0
do count = count + 1
n = n / 5
end return count
endfunction
factorial_factor_5_count(n)
local count = 0
for i = 1, n do
count = count + factor_5_count(i)
endreturn count
endfunction
factorial_trailing_zero_count_v3(n)
return factorial_factor_5_count(n)
end
方法4
方法4的理解難度相對就比較高了,考慮數n1:
n1 = n / 5
他表示的是1到n中帶有因子5的數字的個數
但根據方法3中的講述,我們需要求的是1到n中所有因子5的個數
怎麼通過n1這種計算方式來計算因子5的總數呢?
考慮數n2:
n2 = n / (5 * 5) = n / 25
他表示的是1到n中帶有因子25的數字的個數
則 n1 + n2 就代表1到n(n < 125)中所有因子5的個數,對於更大的n,我們需要繼續計算(這裡理解有些難度,不明白的同學可以多想一想~):
n3 = n / (5 * 5 * 5) = n / 125
n4 = n / (5 * 5 * 5 * 5) = n / 625
然後通過計算
n1 + n2 + n3 + n4 + …
來計算1到n中所有因子5的個數~
**如下:
function
factorial_trailing_zero_count_v4
(n) local count = 0
local factor = 5
while n >= factor do
count = count + math.
floor(n / factor)
factor = factor * 5
endreturn count
end
還有其他方法!?有知道的朋友可以告知下~
ok,我們下次再見吧~
計算n的階乘有多少個尾隨零
之前的思路是根據1 10,10個數乙個區間分析乙個區間產生多少個零,發現這個方法不靠譜,隨後閱讀資料發現以下思路 我們會發現乙個因子2和因子5組合產生乙個0,這樣我們只需統計1到n有多少個因子對,即n!的尾隨零個數,因子2的個數比因子5的個數多,因此我們只需統計出因子5的個數即可,如 統計一次5的倍...
N階乘尾部的0個數
描述 設計乙個演算法,計算出n階乘中尾部零的個數 思路 1 1 2 3 n 1 2 3 2 2 5 2 3 7 2 2 2 3 3 2 5 化成質數相乘,只有2 5才可能得到結果有尾數中有0 2 因為2的個數是比5多的,求0的個數問題就轉化成了求5的個數的問題 3 5 5 5 5 5 5有n個5 得...
一種快速求fibonacci第n個數的演算法
利用動態規則的思路,摒棄傳統的遞迴做法,可以得到一種快速的求fibonacci第n個數的演算法 求第n 從1開始 位fibonacci數 fibonacci數列前兩位為0,1.後面每一位數字等於前兩位數字之和 def fibonacci n if n 2 return n 1f 0 g 1 whil...