zoukankan      html  css  js  c++  java
  • 洛谷 P2529 [SHOI2001]击鼓传花 解题报告

    P2529 [SHOI2001]击鼓传花

    题意:求出(n!)末尾最后一位非0数字

    数据范围:(n<=10^{100})


    我们从简单的开始考虑

    1.显然,(n!)可以被这么表示

    (n!=c imes 2^a imes 5^b)

    显然有(a>b)

    2.末尾的元素即为(c \%10 imes 2^{a-b} \%10)

    显然这个复杂度是我们所不能接受的

    我们发现(5)很特殊

    我们把所有(5)的倍数都取出来(注意取出的是(5)的倍数而不是因数(5)),给每个(5)配一个(2)

    相当于把(5*1,5*2,5*3,...,5*n)中的(5)约去,发现剩下的是一个规模1/5的相同子问题

    (fac(i))表示(i!)的末尾非0数字,则有(fac(i)=fac(lfloor i/5 floor) imes ? \% 10)

    我们想办法求出(?)的贡献

    因为因子(2)消不完,所以末尾必须是偶数

    发现剩下的数可以直接(mod) (10)

    把每(20)位分成一块,对末位的贡献为(6)

    因为$6 imes $任意偶数,末尾不变

    所以答案只需要把20位以内的额外贡献找到就可以

    我们考虑直接把这20位打表,然后递归处理子问题

    复杂度可以接受(高精度我不会算)


    Code:

    #include <cstdio>
    #include <cstring>
    const int N=102;
    struct l_num
    {
        int num[N];
        l_num()
        {
            memset(num,0,sizeof(num));
        }
        l_num(char c[])
        {
            memset(num,0,sizeof(num));
            num[0]=strlen(c);
            for(int i=1;i<=num[0];i++)
                num[i]=c[num[0]-i]-'0';
        }
        l_num friend operator /(l_num n1,int n2)
        {
            for(int i=n1.num[0];i>1;i--)
            {
                n1.num[i-1]+=n1.num[i]%n2*10;
                n1.num[i]/=n2;
            }
            n1.num[1]/=n2;
            if(!n1.num[n1.num[0]]) --n1.num[0];
            return n1;
        }
        int friend operator %(l_num n1,int n2)
        {
            return n1.num[0]==1?n1.num[1]:(n1.num[2]&1)*10+n1.num[1];
        }
    };
    int init[21]={1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2,6};
    char c[103];
    int cal(l_num fac)
    {
        return fac.num[0]?init[fac%20]*cal(fac/5)%10:1;
    }
    int main()
    {
        int t=5;
        while(t--)
        {
            scanf("%s",c);
            l_num fac(c);
            printf("%d
    ",cal(fac));
        }
        return 0;
    }
    
    

    2018.8.9

  • 相关阅读:
    现代软件工程的构建之法
    How do I Check for Duplicate Items in a ListView?
    (转)aspxgridview记录的批量修改
    vs2010简体中文旗舰版智能感知,中文提示,英文提示变化的问题
    (转)怎样成为一名Android开发者
    It’s Not Too Late to Learn How to Code
    (转)手机屏幕VGA QVGA HVGA WVGA区别
    (转)CodeSmithSchemaExplorer类结构详细介绍
    (转)C#控件命名规范
    DataReader 绑定DataGridView的方式
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9450269.html
Copyright © 2011-2022 走看看