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