HDU 5446 Unknown Treasure Lucas+CRT

题意:给n,m,k和p1,p2….pk
求C(n,m)%p1* p2* …. pk
思路:比赛的时候并没有学…..
就是LUACS+CRT模板题

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
typedef long long LL;
#define maxn 10005
const int inf=(1<<28)-1;
LL quick_mod(LL a, LL b,LL p)
{
    LL ans = 1;
    a %= p;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % p;
            b--;
        }
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}

LL C(LL n, LL m,LL p)
{
    if(m > n) return 0;
    LL ans = 1;
    LL a=1,b=1;
    for(int i=1; i<=m; i++)
    {
        a =a* (n + i - m)%p;
        b =b* i%p;
    }
    ans=a*quick_mod(b,p-2,p)%p;
    return ans;
}

LL Lucas(LL n, LL m,LL p)
{
    if(m == 0) return 1;
    return C(n % p, m % p,p) * Lucas(n / p, m / p,p) % p;
}
void exgcd(LL a, LL b, LL &d, LL &x, LL &y)//扩展欧几里德求逆元
{
    if (b == 0)
        d = a, x = 1, y = 0;
    else
    {
        exgcd(b, a%b, d, y, x);
        y -= x * (a / b);
    }
}

LL CRT(LL a[],LL m[],LL n)//中国剩余定理求解
{
    LL aa = a[1];
    LL mm = m[1];
    for (int i=1; i<=n; i++)
    {
        LL sub = (a[i] - aa);
        LL d, x, y;
        exgcd(mm, m[i], d, x, y);
        if (sub % d) return -1;

        LL new_m = m[i]/d;
        new_m = (sub/d*x%new_m+new_m)%new_m;
        aa = mm*new_m+aa;
        mm = mm*m[i]/d;
    }
    aa = (aa+mm)%mm;
    return aa;
}
LL r[maxn],m[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        LL M,n,k;
        scanf("%lld%lld%lld",&M,&n,&k);
        for(int i=1;i<=k;++i)
        {
            scanf("%lld",&m[i]);
            r[i]=Lucas(M,n,m[i]);
        }
        printf("%lld\n",CRT(r,m,k));
    }
}

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