hdu 1066

给出正整数N,请求出N!最右非零的数位的值。


ans(N!)=ans(1234...N)=f(N)g(N)mod10

f(i)=(1234)(6789)(11121314)...(...i)mod10
f(i)=(1234)(6789)(1234)...(...(imod10))mod10

g(i)=51015202530...(i(imod5))

g(i)=f([i/5])5[i/5]=f([i/5])5[i/5]10[i/5]=f([i/5])2[i/5] (2的因子个数远远多于5的因子个数)

f(i) 的实现:当 i>=10 时, f(i) 具有明显周期性, Tf=10 ,只与个位数字有关。
g(i) 的实现: 2 的幂的个位数具有明显周期性,Tg=4 ,只与 [i/5] 的最后两位数字有关。

最后, gcd(TfTg)=20 ,嗯,于是,大家都懂了。


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>

const int MAXN = 1000;

int list[25] = {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};

struct bignumber
{
    int l , n[MAXN];

    void ten()
    {
        for(int i = 1; i < l ;i++)n[i] = n[i+1]; n[l--] = 0;
    }
    void two()
    {
        for(int i = 1 ; i <= l ; i++)n[i] <<= 1;
        for(int i = 1 ; i <= l ; i++){n[i+1]+=n[i]/10,n[i]%=10;}
        l += (n[l+1])?1:0;
    }
}num;

char ch[MAXN] = {'\0'};

int slove()
{
    int ans = 1;
    while (num.l) 
    {
        ans = ans * list[(num.n[2]&1)*10+num.n[1]] % 10; 

        num.two(); num.ten();
    }
    return ans;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("hdu1066.in","r",stdin);
    freopen("hdu1066.out","w",stdout);
#endif  


    while(scanf("%s",ch)!=EOF)
    {
        memset(num.n,0,sizeof(num.n));num.l = 0; 

        int len = strlen(ch);

        for(int i = len-1 ,j = 1 ; i >= 0 ; i--,j++)
            num.n[j] = ch[i] - '0';
        for(int i = len ; i >=1 ; i--)
            if(num.n[i]){num.l = i;break;}

        printf("%d\n",slove());
    }


#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif  
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值