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;
    }
    
  • 相关阅读:
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    how to use automapper in c#, from cf~
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11571737.html
Copyright © 2011-2022 走看看