題目描述
給定一個整數N,那麼N的階乘N!末尾有多少個0呢?(該題取自《編程之美》)
分析求解如果N!= K*10^M,且K不能被10整除,則N!末尾有M個0。考慮N!可以進行質因數分解,N!= (2^X) * (3^Y) * (5^Z)..., 則由於10 = 2*5,所以0的個數只與X和Z相關,每一對2和5相乘得到一個10,所以0的個數M=min(X, Z),顯然2出現的數目比5要多,所以0的個數就是5出現的個數。由此可以寫出如下代碼:
int numOfzero(int N){ int cnt = 0; for (int i=1; i<=N; i++) { int j = i; while (j % 5 == 0) { cnt++; j /= 5; } } return cnt;}
繼續分析可以改進上面的代碼,為求出1到N的因式分解中有多少個5,令Z=N/5 + N/(5^2) + N/(5^3)+...即N/5表示1到N的數中5的倍數貢獻一個5,N/(5^2)表示5^2的倍數再貢獻一個5...舉個簡單的例子,比如求1到100的數因式分解中有多少個5,可以知道5的倍數有20個,25的倍數有4個,所以一共有24個5。代碼如下:
int numOfzero2(int N){ int cnt = 0; while (N) { cnt += N/5; N /= 5; } return cnt;}
上面的分析乏善可陳,這裡需要提到的一點就是其中涉及到的一條算術基本定理,也就是任意大於1的自然數都可以分解為質數的乘積,而且該分解方式是唯一的。定理證明分為兩個部分,存在性和唯一性。證明如下:
存在性
使用反證法來證明,假設存在大於1的自然數不能寫成質數的乘積,把最小的那個稱為n。自然數可以根據其可除性(是否能表示成兩個不是自身的自然數的乘積)分成3類:質數、合數和1。首先,按照定義,n
大於1。其次,n 不是質數,因為質數p可以寫成質數乘積:p=p,這與假設不相符合。因此n只能是合數,但每個合數都可以分解成兩個嚴格小於自身而大於1的自然數的積。設 n = a*b,a和b都是大於1小於n的數,由假設可知,a和b都可以分解為質數的乘積,因此n也可以分解為質數的乘積,所以這與假設矛盾。由此證明所有大於1的自然數都能分解為質數的乘積。
唯一性
當n=1的時候,確實只有一種分解。假設對於自然數n>1,存在兩種因式分解:n=p1...pm
= q1...qk,p1<=...<=pm, q1<=...<=qk。其中p和q都是質數。我們要證明p1=q1...如果不相等,我們可以設p1<q1,從而p1小於所有的q,由於p1和q1是質數,所以它們的最大公約數為1,由歐幾裡德演算法可知存在整數a和b使得a*p1 + b*q1 = 1。因此
a*p1*q2...qk + b*q1*q2...qk = q2...qk. 由於q1...qk = n,因此p1除盡右邊的q2...qk,即q2...qk / q1為整數,且q2...qk有一個質數因子分解,在此因式分解中p1出現,但是q2...qk < n,所以它有一個唯一的因式分解(由歸納法),此矛盾表明,p1最終一定等於q1,所以p1能夠除盡兩個n的因子分解p1...pm和q1...qk,從而p2...pm
= q2...qk < n,另一個因子也相等(由歸納法)。由此完成唯一性的證明。
參考資料
編程之美
具體數學