0
点赞
收藏
分享

微信扫一扫

不要被阶乘吓到

 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! 进行质因数分解。

如:不要被阶乘吓到_编译器_02

由于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;
}


举报

相关推荐

0 条评论