這是給大一第四周出的作業題中的一道,由於沒有開例會,所以在這裏詳細的解釋一下,以發到公衆號推送上面去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個5,10!裏面有2個5(5!和10=2*5裏面的5),15!裏面有3個5(10!和15=3*5裏面的5).......則因此10!末尾有2個零,15!末尾有3個零......
這裏有一個分界線,那就是25時,25裏面有6個5(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}
運行結果:
這篇花的時間也挺久的。。熟練度還是不高,還要繼續努力( ・´ω`・ )