问题描述
给定参数n(n为正整数),请计算n的阶乘n!末尾所含有“0”的个数。
例如,5!=120,其末尾所含有的“0”的个数为1;10!= 3628800,其末尾所含有的“0”的个数为2;20!= 2432902008176640000,其末尾所含有的“0”的个数为4。
问题分析:
显然,对于阶乘增长速度的非常快的,很容易就溢出了。当然就不可能把阶乘算出来,而是要找规律解决。下面用因式分解的思路来考虑:末尾的0可以分解为2*5,一个5,一个2就对应一个0;
下面给出递推过程:
(1)当n<5 时,f(n) =0; 结论成立
(2)当n>=5 时,可以令 n!=[5k*5(k-1)…10*5]*a ,其中n=5k+r ,r(0<=r<5),a是一个不含因子的整数,可看出是一个满足条件的整数;
对于序列5k,5(k-1)…10*5 中在每一个5i中,在区间(5(i-1),5i)内存在一个偶数,即存在一个2与之对应。因此这里的k个‘5’因子 与n!中的末尾0个数是一一对应的。
所以递推公式转化为:
f(n!)=g(5^k * k! *a) = k + g(k!)= k+f(k!); k!是系数的相乘结果。
f(n!)=k+f(k!);
例如: f(5!)= 1+f(1!)=1;
f(10!)=2+f(2!)=2;
下面给出C++两种实现代码:.递归;非递归:
//递归
int n_jie_tail_zeors_recurise(int n)
{
int zeros_num =0;
int k;
if(n < 5)
return 0;
for(k=5;k<=n;k+=5)
{
zeros_num++;
}
return zeros_num + n_jie_tail_zeors_recurise(zeros_num);
}
//非递归
int n_jie_tail_zeros_non_recurse(int n)
{
int zeros_num =0;
int temp = n;
int k=0;
int index=0;
while(temp >5)
{
index =0;
for(k =5;k<=temp;k+=5)
{
zeros_num++;
index++;
}
temp = index;
}
return zeros_num;
}