zoukankan      html  css  js  c++  java
  • 求n得阶乘得最后一位非零数字

    如题,最后一位数好求,他只和最后一位相乘后的最后一位有关,唯一影响我们得是末尾0,而阶乘中末尾0来自于2和5,(10得话可以看成2 * 5),所以有这个思想我们可以筛选出1 * 2 * 3 * .... * n中包含2和5得个数

    如下:

    int get2(int n)
    {
        if(n == 0)return 0;
        return n / 2 + get2(n / 2);
    }
    int get5(int n)
    {
        if(n == 0)return 0;
        return n / 5 + get5(n / 5);
    }
    

    解释:

    对于1 2 3 4 5 6 7 8 9 ^ 25 26 27 28 29 30
    我要想找里面任何一个包含5得数字,一眼看去筛选出含有5得只有:5 10 15 20 25 30,但是有的含有两个5啊,那我就提出一个5,把他降一个形态,然后继续去寻找……
    30 /5 = 6 得到原型 6!,其余得均为无关数,不必去管
    继续筛选1 2 3 4 5 6,这个6得阶乘,是上面筛选完后产生得,可能还存在着得数,这些数将会递归进行二次筛选

    这样我们完成了第一步,筛选完后,你会发现原来的阶乘

    1 2 3 4 5 6 7 8 9 ^ 25 26 27 28 29 30

    变成了

    1 1 3 1 1 3 7 1 9 1 11 3 13 7 3

    这样看反而有所不大直观,但是能够得出得就是最后剩下得就是1 3 7 9(尾数),1没有作用,而 3 7 9 结果观察,他们自身得n次方得位数有个周期

    1 3 9 7

    1 7 9 3

    1 9 1 9

    所以我们就可以取寻找原来那些数含有3,5,7得个数

    还是先看看原型

    1 2 3 4 5 6 7 8 9 ^ 25 26 27 28 29 30

    step 1对于这些数,我们要做得是奇偶分开

    1 3 5 7 9 。。。 2 4 6 8 10.。。。

    对于偶数唯一要做得就是抽2变型(递归step1)

    step2 对于奇数我们可以求取了,奇数中,每10个数中肯定含有1个3,7,9,所以返回得值中有n / 10然后对于非整得数,还要考虑其最后一位得大小选择性得+1 即+(n % 10 >= x)

    然后奇数中还有5,这个根据我们得拆分,是不应该纯在得所以递归 step 2(n/ 5 --- 抽5降形)

    为什么重复step2而不是step1呢?抽了5后不会出现偶数得情况吗??

    因为 奇偶分家得时候,进来的奇数已经不再是一个完整得阶乘了,但是对3 7 9 得寻找毫无影响,因为偶数都一眼找不出来,所以进来得5 是 5 15 25,降型后也是 1 3 5 .。。直接去应用step2

    到此就能够实现了

    int g(int n,int x)
    {
        if(n == 0)return 0;
        return n / 10 + (n % 10 >= x) + g(n / 5,x);
        //这里的5分解后只有奇数没有偶数ggm1,3,5,7....,然后再在奇数里筛选
        //因为10,20,这样的一开始再getx中是筛不进来得!!
    }
    int getx(int n,int x)//寻找这个数中
    {
        if(n == 0)return 0;
        return getx(n / 2,x) + g(n,x);
    }
    int numtable[4][4] ={
        6,2,4,8,
        1,3,9,7,//注意顺序得安排取0得时候代表有4个得时候得余数
        1,7,9,3,
        1,9,1,9
    };
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            int num2 = get2(n) - get2(n-m);
            int num5 = get5(n) - get5(n-m);
            int num3 = getx(n,3) - getx(n-m,3);
            int num7 = getx(n,7) - getx(n-m,7);
            int num9 = getx(n,9) - getx(n-m,9);
            int res = 1;
            if(num5 > num2)
            {
                res = 5;
            }
            else if(num5 < num2)//WRONG 2 :只有不相等得时候才能乘法,因为numtable[0][0]也是有数据得肯定会造成影响
            {
                res *= numtable[0][(num2 - num5)%4];//WRONG 1 :乘上得是多余得2!!!
                res %= 10;
            }
            if(res != 5)
            {
                res *= numtable[1][num3%4];
                res %= 10;
                res *= numtable[2][num7%4];
                res %= 10;
                res *= numtable[3][num9%4];
                res %= 10;
            }
            printf("%d
    ",res);
        }
        return 0;
    }
    
  • 相关阅读:
    Lambda表达式、依赖倒置
    ASP.NET vNext 概述
    Uname
    RHEL4 i386下安装rdesktop【原创】
    Taxonomy of class loader problems encountered when using Jakarta Commons Logging(转)
    How to decompile class file in Java and Eclipse
    先有的资源,能看的速度看,不能看的,抽时间看。说不定那天就真的打不开了(转)
    Google App Engine 学习和实践
    【VBA研究】VBA通过HTTP协议实现邮件轨迹跟踪查询
    js正則表達式语法
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/8672333.html
Copyright © 2011-2022 走看看