zoukankan      html  css  js  c++  java
  • 求n!最后一位非零数

    引子:求n!末尾0的个数

    n!末尾的0来源只有2,5两个质数相乘.所以只需要考察n!中包含多少个2和多少个5.然后取其较小值即为所求.即ans=min(cnt(2),cnt(5)).而转念一想,cnt(2)怎么可能比cnt(5)少呢?所以最终答案改为ans=cnt(5).
    那么问题来了,如何求n!中5的个数呢?cnt(5)=n/5+n/25+n/125......+n/5^log5(n).式中一切浮点运算皆向下取整.

    原题

    以17为例,把1,2,3,...n分成5个一份.

    1 2 3 4 5
    6 7 8 9 10
    11 12 13 14 15
    16 17
    

    每行的最后一个都包含一个5,而这个5最终只会变成0,所以真正有用的是这个数除以5.于是上面数阵等价于

    1 2 3 4 1
    6 7 8 9 2
    1 2 3 4 3
    6 7 
    

    这样一来规律太明显了.假设这个数阵有m整行,也就是n/5的下界,最后剩余k个,也就是n%5.

    1*2*3*4=24
    6*7*8*9=3024
    最后一位都是4,也就是每行相乘(除去每行最后一个数)最后一位都是4,在算上每行最后略去的5,从4中拿出一个2来给5,于是每行最后变成2.
    于是答案呼之欲出了.对于前面的整行m行,结果为
    2^m*m!
    最后再把最后一行的几个数乘上去就可以了.
    

    这个结论还不够简明,表达上不够清晰.
    附上一份林教主的代码

    #include<stdio.h>
    int a[] = {1, 2, 4, 3};//2^k % 5
    int b[] = {1, 1, 2, 6, 4};//n! % 5
    int solve(int n){//求n!的最右非零数 % 5
        if(n < 5)
            return b[n];
        int t = n%5, k = n/5;
        return a[k%4]*solve(t)%5*solve(k)%5;
    }
    int main(){
        int ans = solve(2016);
        if(ans&1) ans =(ans+5)%10;
        printf("%d
    ", ans);
        return 0;
    } 
    

    留个课后思考题,n!的倒数第二位非0数是几?

  • 相关阅读:
    网页显示UIWebView(一个)
    借百度数据,建立你自己的程序
    引水数据--紧凑
    Unity3d 实时折射和反射
    snmp监控磁盘
    Linux snmp监控
    20监控工具
    Java 四舍五入
    Oracle主键操作
    SnmpTrap
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/6181852.html
Copyright © 2011-2022 走看看