atcoder Iroha and a Grid(组合数学)

传送门
组合数学好题。
给你一个 h h h w w w列的网格,其中左下角 a a a b b b列不能走,问从左上角走到右下角有多少种走法(每次只能向右或者向下)


我们考虑分步计数。
我们一共能走的区域是总网格区域去掉一个左下角的,可以看成是一个 b ∗ ( h − a ) b*(h-a) b(ha)的矩形和一个 h ∗ ( w − b ) h*(w-b) h(wb)的矩形拼起来的图案。
于是我们可以枚举两个矩形的交界处来统计答案。
相当于是分步走。
先从起点走到交界处,然后从交界处走到终点。
代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const int N=2e5+5,mod=1e9+7;
int h,w,a,b,fac[N],ifac[N],ans=0,up;
inline int C(int n,int m){return (ll)fac[n]*ifac[m]%mod*ifac[n-m]%mod;}
int main(){
	scanf("%d%d%d%d",&h,&w,&a,&b),up=max(w,h),fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=up<<1;++i)fac[i]=(ll)fac[i-1]*i%mod,ifac[i]=(ll)ifac[mod%i]*(mod-mod/i)%mod;
	for(ri i=2;i<=up<<1;++i)ifac[i]=(ll)ifac[i]*ifac[i-1]%mod;
	for(ri i=1;i<=h-a;++i)(ans+=(ll)C(b+i-2,b-1)*C(h+w-b-i-1,w-b-1)%mod)%=mod;
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值