组合数 + dp思想
先将所有黑点排个序,左上方的优先级最高
则确保对于当前黑点,它所能到达的黑点必定位于排序后序列中的它的后方
然后将(h, w)加入到序列尾端 ++n
对于该序列中的每一个节点( j ),初状态为从(1, 1)抵达该点的方案数,即初始化type[ i ]
但这时会有重复计算。从(1, 1)出发经过数个点的情况被多次计算了,因而必须在内层循环对type[ i ]进行处理
它可以由之前任意一个可以到达它的点( i )的种类数转移,方程为
type[ j ] = type[ j ] - type[ i ] * comb(i - > j) % mod;
其中,comb[i ->j]表示从点i到点j可以走的路径总数
最后type[n]即为所求
1 #include<bits/stdc++.h>
2 #define ll long long
3 using namespace std;
4 const int maxn = 2e5 + 10;
5 const ll mod = 1e9 + 7;
6 struct node
7 {
8 int x;
9 int y;
10 }b[2010];
11
12 bool cmp(const node &i, const node &j)
13 {
14 if(i.x != j.x){
15 return i.x < j.x;
16 }
17 return i.y <= j.y;
18 }
19
20 ll f[maxn];
21 ll inv[maxn];//逆元
22 ll finv[maxn];//逆元阶乘
23
24 int read(){
25 char ch=getchar();int x=0,f=1;
26 while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();}
27 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
28 return x*f;
29 }
30
31 void pre()
32 {
33 f[0] = f[1] = 1;
34 inv[0] = inv[1] = 1;
35 finv[0] = finv[1] = 1;//记得初始化
36 for(ll i = 2 ; i < maxn ; i++){
37 f[i] = f[i - 1] * i % mod;
38 inv[i] = (mod - mod / i) % mod * inv[mod % i] % mod;//线性求逆元
39 }
40 for(ll i = 2 ; i < maxn ; i++){
41 finv[i] = finv[i - 1] * inv[i] % mod;//逆元阶乘
42 }
43 }
44
45 ll type[2020];
46
47 ll comb(ll n, ll m)
48 {
49 if(m == 0 || n < m) return 1;
50 ll tmp = f[n] * finv[n - m] % mod * finv[m] % mod;//此处分母为逆元阶乘
51 return tmp % mod;
52 }
53
54 ll h, w, n;
55
56 bool check(int i, int j)
57 {
58 if(b[i].x <= b[j].x && b[i].y <= b[j].y){
59 return true;
60 }
61 return false;
62 }
63
64 int main(){
65 pre();
66 h = read();
67 w = read();
68 n = read();
69 for(register int i = 1 ; i <= n ; i++){
70 b[i].x = read();
71 b[i].y = read();
72 }
73 sort(b + 1, b + n + 1, cmp);
74 b[++n].x = h;
75 b[n].y = w;
76 for(register int i = 1 ; i <= n ; i++){
77 type[i] = comb(b[i].x + b[i].y - 2, b[i].x - 1) % mod;
78 for(register int j = 1 ; j < i ; j++){
79 if(!check(j, i)) continue;
80 ll tmp = comb(b[i].x - b[j].x + b[i].y - b[j].y, b[i].x - b[j].x) % mod * type[j] % mod;
81 type[i] -= tmp;
82 type[i] = (type[i] + mod) % mod;
83 }
84 }
85 printf("%lld
",type[n] % mod);
86
87 return 0;
88 }