• LETTers比赛第四场Last nonzero Digit in N!


    Last non-zero Digit in N!

    该题数据较大,n可能有数百位,直接计算n!或通过n次计算都必然会超时。关键在于找出数字的规律。对于n<10,直接枚举即可,下面考虑n>=10的情况。

    n!的尾部的0都来自因子5和因子2(一对5&2产生一个0),如果把这些因子去掉,则可符合要求。

    定义F(n)为所要求的数,G(n)为1,2…n中将5的倍数的数换成1后的各项乘积(如:G(15)=1*2*3*4*1*6*7*8*9*1*11*12*13*14*1)(G(n)%10必不为0)。

    则n!=(n/5)!*5^(n/5)*G(n),F(n)=F(n/5)*[5^(n/5)*G(n)%10],这可用递归处理,另外观察到5^(n/5)*G(n)%10=G(n)/2^(n/5)%10,这里G(n)%10(n>=10)其实是个周期为10的周期序列(程序中的table),G(n)/2^(n/5)必为偶数,这样得到一种特殊除法:8/2=4,4/2=2,2/2=6,6/2=8…,这样G(n)/[2^(n/5)]%10只与G(n)%10和(n/5)%4有关。而G(n)%10=table[n%10],n/5%4=n/5%100%4(%100好算,就是最后两位数字)。

    #include<iostream>
    #include<string.h>
    using namespace std;
    #define MAXN 1000
    char n[MAXN];
    int  b[MAXN];
    const int m[10]={1,1,2,6,4,2,2,4,2,8}; // 对小于10的数直接得到非零尾数
    const int table[10]={6,6,2,6,4,4,4,8,4,6};
    const int even[4]={8,4,2,6};
    int div2(int a, int c) // a/(2^c)
    {
        int i;
        for(i=0; i<4 && even[i]!=a; i++);
        if(i>=4)
            return 0;
        return even[(i+c)%4];
    }
    int lastbit(char*s)
    {
        int len=strlen(s);
        if(len<2)
            return m[s[0]-'0'];
        int i, c, bit=1;
        for(i=len-1; i>=0; i--)
            b[len-1-i]=s[i]-'0';
        while(len>1)
        {
            int k = b[0];
            for(i=1,c=b[0]/5; i<=len; i++) // b=b/5(b=b*2/10)
            {
                c = b[i] * 2 + c;
                b[i-1] = c % 10;
                c /= 10;
            }
            len -= !b[len-1];
            bit = bit * div2(table[k],b[0]+b[1]*10) % 10;
        }
        bit = bit * m[b[0]] % 10;
        return bit;
    }
    int main(void)
    {
        while(cin>>n)
            cout<<lastbit(n)<<endl;
        return 0;
    }
  • 相关阅读:
    Android软件常用下载
    布同:如何解决Python中文问题(总结了多位前人经验,初学者必看)
    布同:统计英文单词的个数
    布同:网络服务器的结构设计
    新浪微博快速发布器【正在制作中】
    布同:Python函数帮助查询小工具[v1和v2]
    写概要设计的简单心得
    手写分页 个人感觉还能优化,甚至抽象出来,需要高手讲解
    让我纠结的IIS和他的回收
    今天学了WCF记录一下
  • 原文地址:https://www.cnblogs.com/LETTers/p/2456089.html
Copyright © 2020-2023  润新知