HDU 5446 Unknown Treasure

传送门
裸的中国剩余定理。。。。

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define prt(k) cerr<<#k" = "<<k<<" ";
typedef long long ll;
///Lucas(n, m, p)=c[n%p][m%p]*lucas(n/p, m/p, p); 组合数取模 p<10^5
ll fac[1021100];
ll mul(ll a, ll n, ll m)
{
    ll r = 0;
    for (; n>0; n>>=1,a=(a+a)%m) if(n&1) r = (r + a) % m;
    return r;
}
ll pmod(ll a, ll n, ll m)
{
    a %= m;
    ll r = 1;
    for (; n>0; n>>=1,a=a*a%m) if (n&1) r=mul(r, a, m);
    return r;
}
ll inv(ll a, ll m) { if(a==1) return 1;return pmod(a, m-2, m); }
void get_fac(ll p)
{
    fac[0]=1;
    for(int i=1;i<=p+10;i++)
        fac[i]=(fac[i-1]*i)%p;
}
ll C(ll n,ll m,ll mod)
{
    if (n < m) return 0;
    ll Comb = mul(mul(fac[n], inv(fac[n-m], mod) , mod),
                  inv(fac[m], mod) , mod) ;
    return Comb;
}
ll Lucas(ll n,ll m,ll mod)
{
    if(m==0) return 1;  ll p=mod;
    return mul(C(n%p, m%p, mod) , Lucas(n/p,m/p,mod) , mod) % mod;
}

ll n, m, k;

ll p[33] ;
ll CRT(ll a[], ll m[], int n)
{
    ll M = 1;
    for (int i=0;i<n;i++) M *= m[i];
    ll ret = 0;
    for (int i=0;i<n;i++) {
        ll tm = M / m[i];
        ll x = inv(tm, m[i]);
        ret = (ret + mul( mul(tm, x, M) , a[i] , M)) % M;
    }
    return (ret + M) % M;
}
ll Comb[234][234];

int main()
{
    for (int i=0;i<=60;i++) for (int j=0;j<=i;j++)
        if (j==0 || j==i ) Comb[i][j] = 1;
        else Comb[i][j] = (Comb[i-1][j] + Comb[i-1][j-1]) ;
    int re; cin>>re;
    while (re--)
    {
        cin>>n>>m>>k; for (int i=0;i<k;i++) cin>>p[i];
        ll a[33];
        for (int i=0;i<k;i++) {
            get_fac(p[i]);
            a[i] = Lucas(n, m, p[i]);
        }
        ll ans = CRT(a, p, k);
        cout<<ans<<endl;
    }
    return 0;
}

你可能感兴趣的:(HDU 5446 Unknown Treasure)