HDU 5446 Unknown Treasure(lucas+中國剩餘定理 / CRT)

Lucas + CRT 模版題
中間結果會爆long long
Lucas: Cmnmodpk=ak
CRT:Cmnmod(pk)=ans

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
#define sc(x) scanf("%d",&x)
const int INF=0x3f3f3f3f;
const int maxn=1e5+50;
const int Mod=1000000007;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned int ui;
using namespace std;

typedef long long ll;
ll fac[maxn];

ll qPow(ll x,ll n,ll mod){
    ll ret=1;
    while(n){
        if (n&1) ret=(ret*x)%mod;
        x=(x*x)%mod;
        n>>=1;
    }
    return ret; //x^n%mod
}

void initFac(int Mod){
    //n!
    fac[0]=1;
    for(int i=1;i<=Mod;i++){
        fac[i]=fac[i-1]*i%Mod;
    }
}

ll lucas(ll n,ll k,ll mod){
    //C_n^k%mod
    if (n<0 || k<0 || k>n) return 0;
    ll ret=1;
    while(n && k){
        ll np=n%mod,kp=k%mod;
        if (np<kp) return 0;
        ret=(ret*fac[np]%mod)*qPow(fac[kp]*fac[np-kp]%mod,mod-2,mod)%mod;
        n/=mod; k/=mod;
    }
    return ret;
}

ll extendEuclid(ll a, ll b, ll& x, ll& y) {
    if (b == 0) { x = 1; y = 0; return a; }
    ll d = extendEuclid(b, a % b, y, x);
    y -= x * (a / b);
    return d;
}

ll mul(ll a, ll b, ll mod) {
    a = (a % mod + mod) % mod;
    b = (b % mod + mod) % mod;

    ll ret = 0;
    while (b) {
        if (b & 1) {
            ret += a;
            if (ret >= mod) ret -= mod;
        }
        b >>= 1;
        a <<= 1;
        if (a >= mod) a -= mod;
    }
    return ret;
}

ll CRT(ll a[],ll prime[],int n)
{
    ll M = 1, d, y, x = 0;
    for (int i = 0; i < n; i++) M *= prime[i];
    for (int i = 0; i < n; i++) {
        ll w = M / prime[i];
        extendEuclid(prime[i], w, d, y);
        //x=x+(y*w%M)*a[i]%M;
        x = (x + mul(mul(y, w, M), a[i], M));
    }
    return (x + M) % M;
}

ll a[15];
ll p[15];

int main()
{
#ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif
    int T; scanf("%d",&T);
    while(T--){
        ll n,m,k;
        scanf("%lld %lld %lld",&n,&m,&k);
        for(int i=0;i<k;i++){
            scanf("%lld",&p[i]);
            initFac(p[i]);
            a[i]=lucas(n,m,p[i]);
        }
        printf("%lld\n",CRT(a,p,k));
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章