HDU 3037 Saving Beans (组合+Lucas定理+逆元+快速幂)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3037


Lucas定理

A、B是非负整数,p是质数。A B写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]。
则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0]) mod p同余

即:Lucas(n,m,p)=C(n%p,m%p)*Lucas(n/p,m/p,p) 



AC代码:

#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
using namespace std;

typedef long long LL;
const int N=52;
const LL II=29;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

LL p,xh[100100];

void www()
{
    xh[0]=1;
    for(LL i=1;i<=p;i++)
        xh[i]=xh[i-1]*i%p;
}

LL power(LL a,LL b)
{
    LL ans=1;
    a=a%p;
    while(b)
    {
        if(b&1) ans=(ans*a)%p;
        a=(a*a)%p;
        b=b/2;
    }
    return ans;
}

LL love(LL n,LL m)
{
    LL ans=1;
    while(n&&m)
    {
        LL nn=n%p,mm=m%p;
        if(nn<mm)
            return 0;
        ans=ans*xh[nn]*power(xh[mm]*xh[nn-mm]%p,p-2)%p;
        n/=p;
        m/=p;
    }
    return ans%p;
}

int main()
{
    LL n,m;
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%I64d%I64d%I64d",&n,&m,&p);
        www();

        printf("%I64d\n",love(n+m,n));
    }
    return 0;
}
/*
2
1 2 5
2 1 5
6 4 5
*/


你可能感兴趣的:(HDU 3037 Saving Beans (组合+Lucas定理+逆元+快速幂))