CF 559C

组合数 + 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\n",type[n] % mod);
86     
87     return 0;
88 }

 

posted @ 2020-11-06 11:52  LegendN  阅读(260)  评论(0编辑  收藏  举报