HDU 1124 Factorial 求階乘末尾的零的個數

        這是給大一第四周出的作業題中的一道,由於沒有開例會,所以在這裏詳細的解釋一下,以發到公衆號推送上面去XDD  如果有誤請多多包涵quq,並且能指出來的話感激不盡。

     如果想要學習本題思想解法請閱讀全文,如果只是想要代碼請直接拉到最後方位置。


1.題目描述

(省略原文一大段)總的來說就是求階乘後末尾的零的個數。

2.解題思路

        正常情況肯定想到的是先直接求階乘然後取它末尾的零,但這種辦法對於小數階乘還好辦,數據如果很大了就完全沒有辦法;如果是大數階乘取數組從前往後爲0的數目的話用的時間和空間也特別的多,因爲要先做一次階乘然後再取,因此思考後發現可以採用數學的方法來做。

        一提到階乘末尾有零的數首先想到的就是5!=120,而我們也知道一個數一旦末尾有了零,那麼它不管乘以任何數,得到的結果都至少含有原來個數的零,而這也是這道題的突破點。因此我們5爲步長,所有的操作都是在5!的基礎上進行。可能這時候會有幾個問題:(1)爲什麼不考慮10。因爲以10爲步長的話,像5,15,25這一類的數字計算起來就很麻煩;(2)爲什麼不考慮2*5,分開求2和5的公倍數然後相乘。這個辦法是可以解決5(2*0+5*1),15(2*0+5*3)之類的問題,但是仔細想想要這樣分開實現也是很麻煩的,同時還要考慮2個數各自的取值問題。

       因此我們可以得到,凡是階乘末尾有零的必定是由“由5乘以某個偶數得來的”,所以實際上那些末尾有零的數滿足以下要求:階乘裏面的數(如3!裏面有1,2,3)有5或5與某個數的乘積(如10,15)。

       尋找方法如下:

       例如,在100中,有5,10,15,20,25......90,95,100這些數:

       而5=5*1;10=5*2;15=5*3;20=5*4.。因此5!裏面有1個510!裏面有2個5(5!和10=2*5裏面的5),15!裏面有3個5(10!和15=3*5裏面的5).......則因此10!末尾有2個零,15!末尾有3個零......

      這裏有一個分界線,那就是25時,25裏面有65(20!和25=5*5裏面的2個5),因此在25之後的每個數裏面都實際上會多加1個5,因此25!末尾有6個零,30!末尾有7個零......據此我們可以知道每當數除以5後的餘數仍能再次除以5的話就爲一個分界線,每過一次分界線後就要多加餘數個5,例如25/5=5,5/5=1,它原本是5個5,所以加1之後就是6個零;50/5=10,10/5=2,它原本是10個5,所以加上2個零後就有12個......

    當下一次餘數爲5的時候,此時爲125,爲125/5=25,25/5=5,5/5=1,根據上面的“每過一次分界線後就要多加餘數個5”可知它的5的個數爲25+5+1=31。因此我們可以將這個部分設定爲一個循環加上一個除以5的判定。

3.代碼

      分析清楚過後,我們用代碼表示上述的內容即爲:

1    count=0;//零的個數
2    t=n/5;//n爲輸入的數,這一步的作用是求出含有5的個數
3    while (t!=0)//餘數比5大
4    {
5        count+=t;//含有t個5就有t個零
6        t/=5;//過一次分界線;如果餘數小於5就結束循環
7    }

     總的代碼:

 1#include<stdio.h>
 2int main(void)
 3{
 4    long long int n;//可以求很大的數的階乘
 5    long long int t;
 6    printf("請輸入數字:\n");
 7    scanf("%lld",&n);
 8    long long int count = 0;
 9    t=n/5;
10    while (t!=0)
11    {
12        count+=t;
13        t/=5;
14    }
15    printf("末尾零的個數爲:%lld\n",count);
16    return 0;
17}

     運行結果:


 

     這篇花的時間也挺久的。。熟練度還是不高,還要繼續努力( ・´ω`・ )

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章