首页 > 代码库 > HDU 3037 Saving Beans

HDU 3037 Saving Beans

/*
hdu3037
http://acm.hdu.edu.cn/showproblem.php?pid=3037
lucas 模板题
*/

#include <cstdio>
#include <cmath>
const long long Nmax=100005;
long long p;

long long ex_gcd(long long a,long long b,long long &x,long long &y)//solve x,y in a*x+b*y=ex_gcd(a,b,x,y)=gcd(a,b);
{
    if(b==0)
    {
        x=1LL;
        y=0LL;
        return a;
    }
    long long ans=ex_gcd(b,a%b,x,y);
    long long tmp=x;
    x=y;
    y=tmp-a/b*y;
    return ans;
    //x = x0 + (b/gcd)*t
    //y = y0 – (a/gcd)*t
     
}

long long get(long long a,long long m,long long c)//get x in a*x=c(mod m)
{
    //we can solve x,y in a*x+b*y=c <=> c%gcd(a,b)==0
    long long x,y;
    long long gcd=ex_gcd(a,m,x,y);
    if(c%gcd!=0)
        return -1;//error
    x*=c/gcd;
    if(m<0)
        m=-m;
    long long ans=x%m;
    while(ans<0)
        ans+=m;
    return ans;
}

// long long Cm(long long n,long long m,long long p)//C(n,m)=n!/(m!(n-m)!);
// {
//     long long ans=1LL;
//     ans=fac(n)%p;
//     ans=(ans* (get(fac(m)*fac(n-m),p,1)%p) )%p;
//     return ans;
// }

long long Cm(long long n,long long m,long long p)
{
    long long a=1,b=1;
    if(n<m)
        return 0LL;
    while(m>0)
    {
        a=(a*n)%p;
        b=(b*m)%p;
        n--;
        m--;
    }
    return a*get(b,p,1)%p;
}

//Lucas C(n*p+r,m*p+t)=C(r,t)*Lucas(n,m);
long long lucas(long long n,long long m,long long p) //求C(n,m)%p p最大为10^5。a,b可以很大!  
{  
    if(m==0)
        return 1;
    else 
        return ( (Cm(n%p,m%p,p) %p ) * ( lucas(n/p,m/p,p) %p ) )%p;
}

int main()
{
    // freopen("HDU3037.in","r",stdin);
    long long t;
    long long n,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&n,&m,&p);
        printf("%lld\n",lucas(n+m,m,p));
    }
    return 0;
}

 

HDU 3037 Saving Beans