问题描述:
Given an integer n, return the number of trailing zeroes in n!.
给定一个整数N,那么阶乘N!末尾有多少个0呢? 例如N=10,N!=3628800,则N!的末尾有两个0.
问题求解:
求阶乘的末尾0的个数,其实就是求这个N!能有多少个乘数为10。
如果按照传统的方法,先计算出N!的结果再来看有多少个0,那就很不实际,结果很容易越界。而我们只要求N!中,10作为乘数的个数就可以了。利用10=2*5,只要求2*5的个数即可。
进行质因数分解:N! = (2^x) * (3^y) * (5^z) ……
2*5的个数= min(x, z)。再进一步考虑,发现,能被2整除的数出现的频率高于被5整除的数。即2*5 的个数 m= min(x, z) = z .
根据上面分析,只要计算出z的值就可以得到N!末尾有多少个0.
#include <iostream>
using namespace std;
/* 解法1: 计算i(i = 1,2,3..N)的因式分解中5的指数 */
int SumZero1(int N)
{
int ret = 0;
for(int i=1;i<=N;i++)
{
int j=i;
while(j % 5 == 0)
{
ret++;
j /= 5;
}
}
return ret;
}
/* 解法2: z = [N/5] + [N/(5*5)] + [N/(5*5*5)]...
[N/5]为N中5的个数,[N/(5*5)]为[N/5]中5的个数 ...
Z为N!中含有5的总个数 */
int SumZero2(int N)
{
int ret = 0;
while(N)
{
ret += N / 5;
N = N / 5;
}
return ret;
}
int main()
{
int N=10;
cout << SumZero1(N) << endl;
cout << SumZero2(N) << endl;
return 0;
}
扩展:
用十进制计算30!(30的阶乘),将结果转换成3进制进行表示的话,该进制下的结果末尾会有多少个0? 答案14
计算N!下三进制结果末尾有多少个0,其实就是计算三进制中的3被移位了多少次,就像二进制一样,每乘以2就向左移一位,末尾补0,因此这道题只要将N!因式分解成3^m*other,m就是答案。
技巧性的解法就是m=N/3+N/(3^2)+N/(3^3)….+N(3^k) (k<=N/3)。