zoukankan      html  css  js  c++  java
  • yzoj P1122 阶乘 题解

    T组数据,给出N,求出N!最右边非零的数。

    对于30%的数据,N <= 30,T<=10。

    对于全部的数据,N <= 10^2009,T<=30。

    一道数学题

    解析

    N!/(10x)最后一位数字即是结果。10x进行拆分,变成5^x* 2x。怎么除以5x呢,好办,乘的时候含有5的倍数的一项全部不乘进去,再递归此过程。即

    1 2 3 4 (15) 6 7 8 9 (25)

    11 12 13 14 (35)16 17 18 19 (45)

    21 22 23 24 (55) 26 27 28 29 (65) ...

    再递归处理

    1 2 3 4 (1*5) 6

    而且可以发现,不算5倍数一项进去,每十个一组,最末尾结果是一样的:6,且6*6还是6!

    接下来的问题,怎么除2^x呢?

    分析发现:

    2^0 = 1

    2^1 = 2

    2^2 = 4

    2^3 = 8

    2^4 =16=(6)

    且2,4,6,8乘以6最末尾还是原来的数。所以,可以分析看x%4是多少,若为1,说明原来的结果相当于多乘了一个2(其他的那些2刚好是4的倍数,不影响结果),所以,我们本来是要除以2的,但是很显然对结果再补乘3个2(2^3)即可消除影响,得到正确答案。其他情况同理。至此,思路理顺。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int T,n,ans,mod,rest,x;
    bool flag;
    const int v[10]={1,1,2,6,4,4,4,8,4,6};
    char s[3000];
    int a[3000];
    const int k[4]={6,8,4,2};
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%s",s);
            memset(a,0,sizeof(a));
            n=strlen(s);
            for(int i=1;i<=n;++i){
                a[i]=s[n-i]-'0';
            }
            ans=1;
            mod=0;
            flag=0;
            while(1){
                rest=0;
                ans=(ans*v[a[1]])%10; 
                if(n>1) ans=(ans*6)%10;
                for(int i=n;i>=1;i--){
                    x=rest*10+a[i];
                    rest=x%5;a[i]=x/5;
                }
                while((n>0)&&(a[n]==0)) n--;
                if(n==0) break;
                flag=true;
                mod=(mod+a[2]*10+a[1])%4; 
            }
            if(flag) ans=(ans*k[mod])%10;
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Python获取 东方财富 7x24小时全球快讯
    Elasticsearch 环境配置
    可执行jar包与依赖jar包
    IDEA注释模板
    CKEditor
    解决让浏览器兼容ES6特性
    asp.net一个非常简单的分页
    Asp.Net真分页技术
    jsp选项卡导航实现——模板
    nodejs类比Java中:JVM
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11416508.html
Copyright © 2011-2022 走看看