不要被阶乘吓倒

题目描述

给定一个整数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,另一个因子也相等(由归纳法)。由此完成唯一性的证明。


参考资料

编程之美

具体数学



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值