bzoj1308: fac

来源:互联网 发布:广西航信金税盘软件 编辑:程序博客网 时间:2024/06/12 03:44

传送门
题目看上去非常不可做。
考虑缩小答案规模。
首先将25!拆分:
25!=(12345)(678910)(1112131415)(1617181920)(2122232425)
将每一组末尾的模5为0的数除以5,并且和前面的2消掉,得到
=(1134)(3789)(1161314)(8171819)(21111314)(12345)
前面每一坨东西末尾都是2。
于是我们没进行依次这样的操作,规模变为原来的1/5
多迭代几次就行了。

#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define N 100100using namespace std;char s[505];int a[505];int biao[25]={    1,1,2,6,4,    2,2,4,2,8,    8,8,6,8,2,    8,8,6,8,2,    4,4,8,4,6};int mi[4]={6,2,4,8};int solve(int *a){    int m,x;    m=a[2]*10+a[1];    if (a[0]<=2&&m<25) return biao[m];    m=0;    int b[505];    memset(b,0,sizeof(b));    for (int i=a[0];i>=1;i--){        m=m*10+a[i];        b[i]=m/25;        m%=25;    }    b[0]=a[0];    while (b[0]&&!b[b[0]]) b[0]--;    x=b[1]+b[2]*10;    for (int i=1;i<=a[0];i++) b[i]*=5;    for (int i=1;i<=a[0];i++){        b[i+1]+=b[i]/10;        b[i]%=10;    }    if (b[b[0]+1]) b[0]++;    return solve(b)*biao[m]*mi[x%4]%10;}int main(){    while (scanf("%s",s+1)!=EOF){        memset(a,0,sizeof(a));        a[0]=strlen(s+1);        for (int i=1;i<=a[0];i++) a[i]=s[i]-'0';        for (int i=1,j=a[0];i<j;i++,j--)            swap(a[i],a[j]);        printf("%d\n",solve(a));    }}
阅读全文
0 0