标签: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,,,,
)
#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;
}
不敢相信的是,如果阶乘打表的话,时间是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