有趣的演算法(一)——n階層尾部有幾個0
阿新 • • 發佈:2022-05-03
有趣的演算法(一)——n階層尾部有幾個0
(原創內容,轉載請註明來源,謝謝)
最近在網上看到好幾次這個題目,覺得挺有意思,則準備用PHP進行實現。
1、題目
給一個非負整數n,確定n!的尾部有幾個0。
2、輸入輸出示例
輸入 1,輸出 0。 輸入6,輸出1。
3、解
1)最常規的方法,會想到先求解n!,再通過除以10取餘數的方式進行。但是此方式求解速度較慢,另外n的值比較大的時候,會產生資料溢位,無法求出n!的值。
程式碼段如下:
if(2>$n)$return 0; $res= 1; for($i=2;$i<=$n;$i++){ $res *= $i; } $zeroNum = 0; while(0 == $n%10){ $zeroNum++; $n = $n/10; } return $zeroNum;
2)由於n! =1*2*3…*n,再分析10=2*5,因此,要確定結尾有幾個0,只需要確定n是由多少個2*5組成就行。
觀察序列1、2…n,發現明顯2的數量遠多於5,例如1-10裡面,2的因子的數量有8個(其中4=2*2,8=2*2*2)而5的因子只有2個。
因此,要求n!的結尾有幾個0,題目就轉換成1,2…n共有幾個5的因子。該方案有3種求解方式。
1)較慢的求解方式,即遍歷1,2..n,把5的因子進行相加
程式碼段如下:
$fiveNum = 0; for($i=1;$i<=n;$i++){ $tmpNum = $i; while(1 <= $tmpNum/5){ $fiveNum++; $ tmpNum =floor($tmpNum/5); } } return $fiveNum;
2)稍快的求解方法,分析5的因子的構成,發現5、10、15…等數才有5的因子,因此上述的迴圈可以改成如下形式。
程式碼段如下:
$fiveNum = 0;
for($i=5;$i<=n;$i=$i+5){//從5開始遍歷,每次步長為5,減少迴圈次數
$tmpNum = $i;
while(1 <= $tmpNum/5){
$fiveNum++;
$ tmpNum =floor($tmpNum/5);
}
}
return $fiveNum;
3)更快的求解方法,再對5、10、15…等數字進行分析,發現凡是5的倍數的都有1個5的因子,25的倍數的都有2個5的因子,125的倍數的都有3個5的因子。
因此,將n/5,求得的結果即為5的倍數的個數;再將n除以5,求得的結果是25的倍數的個數,以此類推求解。
程式碼段如下:
$fiveNum = 0;
while(1 <=$n){
$fiveNum += $n/5;
$n = $n/5;
}
return $fiveNum;
——written by linhxx 2017.07.12