CF559C

\(x,y\) 的棋盘,从左上角走到右下角,输出方案,\(C_{x+y-2}^{x-1}\)

考虑容斥掉黑色的。把黑色的格子按行、列排序。假设左下角是第\(0\)个黑色格子,右下角是第\(N+1\)个黑格子

\(F[i]\)表示从左上角走到排序后的第\(i\)个黑色格子,不经其他黑色格子的个数

\[F[i]=C_{x_i+y_i-2}^{x_i-1}-\sum_{j=0}^{i-1}F[j]*C_{x_i-x_j+y_i-y_j}^{x_i-x_j}(x_i\ge x_j,y_i\ge y_j) \]

#include<cstdio>
#include<iostream>
#include<algorithm>
#define re register
using namespace std;
#define x first
#define y second
const int N = 2005;
pair<int,int>a[N];
int h,w,n,f[N],mod = 1e9 + 7;
long long jc[200005],inv[200005];
inline int C(int n,int m){return jc[n] * inv[m] % mod * inv[n-m] % mod;}
inline int qpow(long long a,int b){
	long long ans = 1;
	for(;b;b >>= 1){
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
	} return ans;
}
int main(){
	scanf("%d%d%d",&h,&w,&n);
	for(re int i = 1;i <= n;++i) scanf("%d%d",&a[i].x,&a[i].y);
	jc[0] = inv[0] = 1;
	for(re int i = 1;i <= 200000;++i){
		jc[i] = jc[i-1] * i % mod;
		inv[i] = qpow(jc[i],mod - 2);
	}
	sort(a + 1,a + n + 1);
	a[n + 1].x = h,a[n + 1].y = w;
	for(re int i = 1;i <= n + 1;++i){
		f[i] = C(a[i].x + a[i].y - 2,a[i].x - 1);
		for(re int j = 1;j < i;++j){
			if(a[j].x > a[i].x || a[j].y > a[i].y) continue;
			f[i] = (f[i] - (long long)f[j] * C(a[i].x+a[i].y-a[j].x-a[j].y,a[i].x-a[j].x)) % mod;
		}
	}
	cout << (f[n + 1] + mod) % mod;
}
posted @ 2020-09-05 19:37  INFP  阅读(238)  评论(0编辑  收藏  举报