1. 程式人生 > 其它 >有趣的演算法(一)——n階層尾部有幾個0

有趣的演算法(一)——n階層尾部有幾個0

有趣的演算法(一)——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