1.前言
阶乘在我们日常代码中,很多地方都能用到,但不少人都比较怕它,下面两个问题我们来看看。
- 给定一个整数N,求N的阶乘N!末尾有几个0。如N = 10, N! = 3628800,所以10的阶乘末尾有2个0。
2.分析和解法
事实上,要是不考虑溢出问题,大部分同学先求出N!的值,再通过先 %10 再 /10 去算,也是能算对的。但现实上,先不说这种方法时间复杂度高,更重要的是它会溢出,导致结果错误。
当我们遇到这种问题时,先考虑一下,那些数相乘可以得到 ‘10’(因为有10才会有0),用这种角度去考虑问题,这条题就变得简单了。
首先我们可以把 N! = K * 10^M ,且K不能被10整除,那么N! 末尾有M个0。然后再考虑对 N! 进行质因数分解。
如:
由于10 = 2 * 5,所以M只和x 和 z 有关系,每一对2 * 5 都有一个0,即 M = Min(x,z)。能被2整除的数比能被5整除的数出现的概率大很多,所以不难看出x 比 z 大,则M的值和z相关。
由于上面的分析得知,只要求出z的值,就可求出N!末尾0的个数。
通常求z的值,我们会回归到N!上求,如:N!,i = (1 * 2 * 3 * ····· * N),只要计算出 ‘i’ 的因式分解中5的指数,然后求和。
3.代码:
#define _CRT_SECURE_NO_WARNINGS //这就话是在VS编译器下要加上的,其他的不用
#include<stdio.h>
int Fac(int n)
{
int ret = 0;
for (int i = 1; i <= n; i++)
{
int j = i;
while (j % 5 == 0)
{
j /= 5;
ret++;
}
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fac(n);
printf("%d", ret);
return 0;
}