码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3037 Saving Beans(lucas定理)

时间:2014-08-01 16:05:32      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   os   io   for   2014   

题目大意:豆子数i (1~m)分到n颗树上。  树可以为空,那么对于每个i,分配方式是 C(n+i-1,n-1)......于是我用for(i=0-->m)做,不幸超时,m太大。


不过竟然公式可以化简: 

for(int i=0;i<=m;i++)

    C(n+i-1,n-1)=C(n+i-1,i)

组合原理:

公式 C(n,k) = C(n-1,k)+C(n-1,k-1)

C(n-1,0)+C(n,1)+...+C(n+m-1,m)

= C(n,0)+C(n,1)+C(n+1,2)+...+C(n+m-1,m)

= C(n+m,m)

[p.s,   C(n-1,0)=C(n,0)==0,,,,bubuko.com,布布扣)



#include<iostream>
#include<cstdio>
#include<cmath>

using namespace std;
#define bug(a) cout<<"bug--->"<<a<<endl;

typedef long long LL;

LL qpow(LL a,LL b,LL p)
{
    LL ans=1;
    while(b)
    {
        if(b&1)
            ans=(ans*a)%p;
        b>>=1;
        a=(a*a)%p;
    }
    return ans;
}

LL C(LL m,LL n,LL p)
{
    LL s1=1,s2=1;
    if(n>m) return 0;
    if(m-n<n) n=m-n;
    for(int i=1;i<=n;i++)
    {
        s1=s1*(m-(i-1))%p;
        s2=s2*i%p;
    }
    return s1*qpow(s2,p-2,p)%p;
}

LL lucas(LL m,LL n,LL p)
{
    if(!n)
        return 1;
    return C(m%p,n%p,p)*lucas(m/p,n/p,p)%p;
}


int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        LL n,m,p;
        scanf("%I64d%I64d%I64d",&n,&m,&p);
        LL res;
        res=lucas(n+m,m,p);

        printf("%I64d\n",res);
    }

    return 0;
}
bubuko.com,布布扣

不敢相信的是,如果阶乘打表的话,时间是1468MS.

不打的话是 531MS(程序如上)




HDU 3037 Saving Beans(lucas定理),布布扣,bubuko.com

HDU 3037 Saving Beans(lucas定理)

标签:des   style   blog   http   os   io   for   2014   

原文地址:http://blog.csdn.net/code_or_code/article/details/38337573

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!