zoukankan      html  css  js  c++  java
  • Hihocder 1639 : 图书馆 (组合数+唯一分解 求最后一位)(妙)

     给定n,(n<=10^3),然后输入n的数a[i],(a[i]<=1e10),求ans=(a1+a2+a3...an)! / (a1!*a2!*a3!...an!) 的结果的最一位数。

    适用问题,n种物品,求全排种类,结果%10。

     

    猜想1,斯特林公式,斯特林公式虽然误差越来越小,但是最后一位的误差是难以消除的,虽然求位数还稳,但是求最后一位几乎不会对。

    猜想2,a[]达到一定程度,答案是0,此种情况必须保证ans的2因子和5因子数都>0,小范围唯一分解,但依然有30%数据过不去。

    猜想3:唯一分解,但是素数太多,而且又得具体到每一个的逆元,难以实现。

     

    猜想4:将ans转化为5的倍数*非5的倍数,以及2的倍数以及非2的倍数,然后剩余定理得计解。

                即,将ans%10,改为%素数p,p=2时:ans2=ans%2;      p=5时:ans5=ans%5,然后中国剩余定理得到ans%10;

                以5为例,算出分解后5因子的个数x:令ans5=((5^x) *y)/z%5,如果x>0,则ans5%5=0;否则得到分子的y和z。 得到ans5=(y/z)% 5。

    得到x的具体实现:

              以5为例,N!= (5^x)*y ,则x=N/5+N/5/5+N/5/5/5...。对于不是5的倍数的部分,以5为循环节计算。 

              坑点在于:5的倍数里面的数一定要算干净,所以要一层一层继续算系数,如:100=5*5*2,这个2是有用的,我就是这里没想到然后挂了。

       1,2,3,4,5,6,7,8,9,10,11...=1,2,3,4,1*5,1,2,3,4,2*5,1...  (循环节为5) = [ (24%5)^ (n/5) ]%5 * (5^x) * 1*2*3 ...(后面的123是系数)

     

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    using namespace std;
    #define ll long long
    ll a[10],ans2,ans5, x[1100],sum;
    int qpow(int n,ll m,int Mod)
    {
        int res=1;n%=Mod;
        while(m){
            if(m&1) res=n*res%Mod;
            n=n*n%Mod;
            m>>=1;
        } return res;
    }
    void get(int opt,ll x,int sig)
    {
        ll tmp=x;
        if(sig==1||sig==-1){
            if(tmp){
                a[opt]+=sig*(tmp/opt);
                tmp/=opt;
            }
            if(tmp){
                get(opt,tmp,1*sig);    //5的倍数的系数不要搞忘 
                get(opt,tmp,2*sig);
            }
        }
        else{
            tmp=1;
            for(int i=1;i<opt;i++){
                tmp=tmp*i%opt;
            }
            tmp=qpow(tmp,x/opt,opt);
            for(ll i=(x/opt)*opt+1;i<=x;i++)  tmp=tmp*(i%opt)%opt;
            if(opt==2&&sig==2)  a[6]=a[6]*tmp%opt;
            if(opt==5&&sig==2)  a[7]=a[7]*tmp%opt;
            if(opt==2&&sig==-2) a[8]=a[8]*tmp%opt;
            if(opt==5&&sig==-2) a[9]=a[9]*tmp%opt;
        }
    }
    int main()
    {
        int T,n;
        scanf("%d",&T);
        while(T--){
            sum=0; ans2=ans5=0;
            a[2]=a[5]=0; a[6]=a[7]=a[8]=a[9]=1;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%lld",&x[i]);
                sum+=x[i];
            }
            get(2,sum,1);    //正数表示在分子 
            get(2,sum,2);
            get(5,sum,1);   //1表示2或5的幂,可以加。  
            get(5,sum,2);   //1表示非2或5的幂。  
            for(int i=1;i<=n;i++){
                get(2,x[i],-1); //负数表示在分母 
                get(2,x[i],-2);
                get(5,x[i],-1);
                get(5,x[i],-2);
            }
            if(a[2]>0&&a[5]>0){ //下面的可以不算,但是算也花不了多少时间。 
                printf("0
    ");
                continue;
            }
            
            ans2=qpow(2,a[2],2);
            ans2=ans2*a[6]%2;
            ans2=ans2*qpow(a[8],1,2)%2;
        
            ans5=qpow(5,a[5],5);
            ans5=ans5*a[7]%5;
            ans5=ans5*qpow(a[9],3,5)%5;
            
            printf("%lld
    ",(5*ans2+16*ans5)%10); //5和16都是逆元算的
        } return 0;
    }
  • 相关阅读:
    了解 NoSQL 的必读资料
    关于什么时候用assert(断言)的思考
    这次见到了一些大侠
    NetBeans 时事通讯(刊号 # 87 Jan 12, 2010)
    动态链接库dll,静态链接库lib, 导入库lib
    新女性十得 写得了代码,查得出异常
    记录系统乱谈
    新女性十得 写得了代码,查得出异常
    fullpage.js禁止滚动
    RunningMapReduceExampleTFIDF hadoopclusternet This document describes how to run the TFIDF MapReduce example against ascii books. This project is for those who wants to experiment hadoop as a skunkworks in a small cluster (110 nodes) Google Pro
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8446881.html
Copyright © 2011-2022 走看看