zoukankan      html  css  js  c++  java
  • HDU-5446-UnknownTreasure(组合数,中国剩余定理)

    链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5446

    题意:

    On the way to the next secret treasure hiding place, the mathematician discovered a cave unknown to the map. The mathematician entered the cave because it is there. Somewhere deep in the cave, she found a treasure chest with a combination lock and some numbers on it. After quite a research, the mathematician found out that the correct combination to the lock would be obtained by calculating how many ways are there to pick m different apples among n of them and modulo it with M. M is the product of several different primes.

    思路:

    lucas定理,p为素数时。
    C(n, m) = C(n/p, m/p)+C(n%p, m%p).
    对每个pi算出值,然后中国剩余定理求解。
    因为数值较大。。很容易溢出,快速乘,顺序也会导致溢出。。
    求逆元的时候,用快速幂会溢出,可以把快速幂里面的乘法用快速乘。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    
    using namespace std;
    typedef long long LL;
    const int INF = 1e9;
    
    const int MAXN = 1e5+10;
    const int MOD = 1e9+7;
    
    LL F[MAXN], Finv[MAXN];
    LL P[MAXN], A[MAXN];
    
    LL MulMod(LL a, LL b, LL mod)
    {
        LL res = 0;
        while(b>0)
        {
            if (b&1)
                res = (res+a)%mod;
            a = (a+a)%mod;
            b >>= 1;
        }
        return res;
    }
    
    LL PowMod(LL a, LL b, LL mod)
    {
        LL res = 1;
        while(b>0)
        {
            if (b&1)
                res = res*a%mod;
            a = a*a%mod;
            b >>= 1;
        }
        return res;
    }
    
    void Init(LL n, LL m, LL mod)
    {
        F[0] = F[1] = 1;
        for (LL i = 2;i <= n;i++)
            F[i] = F[i-1]*i%mod;
        Finv[m] = PowMod(F[m], mod-2, mod);
        Finv[n-m] = PowMod(F[n-m], mod-2, mod);
    }
    
    LL Comb(LL n, LL m, LL mod)
    {
        if (m > n)
            return 0;
        if (m == n)
            return 1;
        Init(n, m, mod);
        return F[n]*Finv[m]%mod*Finv[n-m]%mod;
    }
    
    LL Lucas(LL n, LL m, LL mod)
    {
        if (m == 0)
            return 1;
        return MulMod(Lucas(n/mod, m/mod, mod), Comb(n%mod, m%mod, mod), mod);
    }
    
    void ExGCD(LL a, LL b, LL &x, LL &y)
    {
        if (b == 0)
        {
            x = 1, y = 0;
            return;
        }
        ExGCD(b, a%b, x, y);
        LL tmp = x;
        x = y;
        y = tmp-a/b*y;
    }
    
    LL CRT(int k)
    {
        LL Pm = 1;
        LL res = 0;
        for (int i = 1;i <= k;i++)
            Pm *= P[i];
        for (int i = 1;i <= k;i++)
        {
            LL x, y;
            LL mi = Pm/P[i];
            ExGCD(mi, P[i], x, y);
            res = (res+MulMod(MulMod(x, mi, Pm), A[i], Pm))%Pm;
        }
        return (res+Pm)%Pm;
    }
    
    int main()
    {
        int t, k;
        LL n, m;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%lld%lld%d", &n, &m, &k);
            for (int i = 1;i <= k;i++)
                scanf("%lld", &P[i]);
            for (int i = 1;i <= k;i++)
                A[i] = Lucas(n, m, P[i]);
            printf("%lld
    ", CRT(k));
    
        }
    
        return 0;
    }
    
  • 相关阅读:
    Android中的Keyevent
    Android的RecyclerView
    Android中的Context
    Android中数据的传递以及对象序列化
    Android中的多线程编程
    Android中的dp, px, pt
    Android中的内容提供器
    Android中的数据保存
    Android中ListView的用法
    Android中Activity的启动模式
  • 原文地址:https://www.cnblogs.com/YDDDD/p/11809067.html
Copyright © 2011-2022 走看看