HDU 5698 组合数学

</pre>传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5698</p><p>
// 计算走i步的方法数</p>// 走i步 ,可以分解为在x方向上走的 x1,x2,...,xi
// 在y1,y2,..yi 步// 就是将 n-1分解为i的不为0的数,就相当于在n-2个空里插入i-1个版
// 将 m-1 分解为i个不为0的数
// 也就是 C(n-2,i-1)*C(m-2,i-1)
//<span style="white-space:pre"> </span>总数也就是sum(C(n-2,i-1)*C(m-2,i-1)) (for i=1 to min(n-1,m-1))
//  不妨变形一下换下i的取值范围 也就有sum C(n-2,i)*C(m-2,i)<span style="white-space:pre"> </span>(for i=0 to min(n-2,m-2))
// 再利用C(n,m)=C(n,n-m)// 就有sum C(n-2,i)*C(m-2,m-2-i)<span style="white-space:pre"> </span>(for i=0 to min(n-2,m-2))
// 而C(n-2+m-2,m-2)就是从n+m-4个数里面选择出m-2个数的组合数
// 按照从前n-2个数里面选择的个数i来分类的话,有i=0 to i=min(n-2,m-2)
// 可以这样考虑 相当于从n-2 + m-2 个数 里面 选出 i + (m-2-i)=(m-2) 个数的个数
// 因为C(n-2,i):从前n-2 个数里面选出 i个数
//   C(m-2,m-2-i):那么就要从剩余的m-2个数里面选出(m-2-i)
// 按照乘法原理:这一类有C(n-2,i)*C(m-2,m-2-i)种
//   按照加法原理 就是sum C(n-2,i)*C(m-2,m-2-i) (for i=0 to min(n-2,m-2) )
// 这就证明了 C(n-2+m-2,m-2)==sum(C(n-2,i-1)*C(m-2,i-1)) (for i=1 to min(n-1,m-1))<p>// multiply case wa 1</p><p>//百度之星原题,上次就不会写,这次有没有写出来,还是听同学才知道思路</p><pre name="code" class="cpp">
#include<cstdio>
#include<iostream>
#include<algorithm>
#define MOD 1000000007
using namespace std;
typedef long long LL;
LL quickmod(LL b,LL p,LL mod)
{
LL res=1;
b=b%mod;
while(p){
if(p&1)
res=(res*b)%mod;
b=(b*b)%mod;
p>>=1;
}
return res;
}
LL inverse(LL x,LL mod)
{
return quickmod(x,mod-2,mod);
}
LL C(LL n,LL m,LL mod)
{
LL a=1,b=1,res=1;
for(int i=n;i>max(m,n-m);i--){
a=a*i%mod;
b=b*(n-i+1)%mod;
}
//cout<<inverse(b,mod)<<endl;
return a*inverse(b,mod)%mod;
}
int main()
{
LL n,m;
while(cin>>n>>m)
cout<<C(n+m-4,m-2,MOD)<<endl;
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值