2018.12.19 atcoder Iroha and a Grid(组合数学)

时间:2023-03-09 13:02:37
2018.12.19 atcoder Iroha and a Grid(组合数学)

传送门

组合数学好题。

给你一个hhh行www列的网格,其中左下角aaa行bbb列不能走,问从左上角走到右下角有多少种走法(每次只能向右或者向下)


我们考虑分步计数。

我们一共能走的区域是总网格区域去掉一个左下角的,可以看成是一个b∗(h−a)b*(h-a)b∗(h−a)的矩形和一个h∗(w−b)h*(w-b)h∗(w−b)的矩形拼起来的图案。

于是我们可以枚举两个矩形的交界处来统计答案。

相当于是分步走。

先从起点走到交界处,然后从交界处走到终点。

代码:

#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;
}