zoukankan      html  css  js  c++  java
  • HDU-5446 Unknown Treasure

    题目描述

    给出(n)(m)以及(k)个质数,设(M)为$prod^{k}_{i=1}p_i (,)p_i(互不相同,求)C(n,m)%M$

    Input

    第一行一个(T)表示数据组数。

    对于每组数据第一行(n),(m),(k)

    第二行(k)个质数,其互不相同。

    (1≤m≤n≤10^{18})

    (1≤k≤10)

    (p_i≤10^5)

    Output

    对于每组数据输出答案。

    Sample Input

    1
    9 5 2
    3 5
    

    Sample Output

    6
    

    扩展卢卡斯定理即可。

    首先,对于一个模数为质数的的组合数,我们可以直接利用卢卡斯定理。

    (C(n,m)\%p=C(n/p,m/p)*C(n\%p,m\%p)\%p)

    可是题目中给出是一个合数,不是质数,那咋办呀?

    我们发现模数最多由不超过(10)个不同的质数组成,对于一个(C(n,m)),我们可以直接求出对于每个质数的取模结果,设第(i)个结果为(res_i)

    则我们就有一个方程组

    [egin{cases} C(n,m)=res_1\%p_1 \ C(n,m)=res_2\%p_2 \ ...... \ C(n,m)=res_k\%p_k end{cases} ]

    我们直接利用中国剩余定理合并即可。

    #include <cstdio>
    #include <iostream>
    
    using namespace std;
    
    #define int long long
    #define reg register
    #define clr(a,b) memset(a,b,sizeof a)
    #define Mod(x) (x>=mod)&&(x-=mod)
    #define abs(a) ((a)<0?-(a):(a))
    #define debug(x) cerr<<#x<<"="<<x<<endl;
    #define debug2(x,y) cerr<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl;
    #define debug3(x,y,z) cerr<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl;
    #define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
    #define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
    #define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
    #define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
    #pragma GCC optimize(2)
    
    inline int Read(void) {
        int res=0,f=1;
        char c;
        while(c=getchar(),c<48||c>57)if(c=='-')f=0;
        do res=(res<<3)+(res<<1)+(c^48);
        while(c=getchar(),c>=48&&c<=57);
        return f?res:-res;
    }
    
    template<class T>inline bool Min(T &a, T const&b) {
        return a>b?a=b,1:0;
    }
    template<class T>inline bool Max(T &a, T const&b) {
        return a<b?a=b,1:0;
    }
    const int N=25,M=1e5+5;
    
    int n,m,k,res[N],mod[N],a[N],pos[N];
    
    int Exgcd(int a, int b, int &x, int &y) {
        if(!b) {
            x=1,y=0;
            return a;
        }
        int g=Exgcd(b,a%b,y,x);
        y-=a/b*x;
        return g;
    }
    
    inline int Excrt(void) {
        int M=mod[1],ans=res[1],x,y;
        rep(i,2,k) {
            int g=Exgcd(M,mod[i],x,y);
            if((res[i]-ans)%g)return -1;
            x*=(res[i]-ans)/g,y=mod[i]/g,x=(x%y+y)%y;
            ans=M*x+ans,M=M/g*mod[i],ans%=M;
        }
        int z=(ans%M+M)%M;
        return z;
    }
    
    int Mod;
    
    int Pow(int x,int y) {
        int res=1;
        while(y) {
            if(y&1)res=(res*x)%Mod;
            x=(x*x)%Mod,y>>=1;
        }
        return res;
    }
    
    inline int C(int x,int y) {
        if(y>x)return 0;
        int up=1,down=1;
        rep(i,x-y+1,x)up=up*i%Mod;
        rep(i,1,y)down=down*i%Mod;
        return up*Pow(down,Mod-2)%Mod;
    }
    
    int Lucas(int x,int y) {
        if(!y)return 1;
        return Lucas(x/Mod,y/Mod)*C(x%Mod,y%Mod)%Mod;
    }
    
    inline void _main(void) {
        int T=Read(),Case=0;
        while(T--) {
            n=Read(),m=Read(),k=Read();
            rep(i,1,k) Mod=mod[i]=Read(),res[i]=Lucas(n,m);
            printf("%lld
    ",Excrt());
        }
    }
    
    signed main() {
        _main();
        return 0;
    }
    
  • 相关阅读:
    Web开发者需具备的8个好习惯
    全球十大搜索引擎排名
    ContextWrapper
    PackageManager
    重写equals方法的注意事项
    StackOverflow 并不只是一个问答网站
    android 中ids.xml资源的使用
    The method dismissDialog(int) from the type Activity is deprecated
    百度员工离职总结:如何做个好员工?
    Mysql 自动化任务
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11571737.html
Copyright © 2011-2022 走看看