zoukankan      html  css  js  c++  java
  • 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
    ",type[n] % mod);
    86     
    87     return 0;
    88 }
  • 相关阅读:
    华为网络层协议介绍
    华为交换机基本原理
    对网络布线与数制转换粗浅认识
    对 计算机网络参考模型新认识
    我对5G的初步认识
    三层交换机单臂路由
    同网段中不同vlan间,客户机从服务器中下载数据
    Telnet远程配置
    华为模拟器里使用RIP协议跨越主类网络边界的实验现象
    7.10 IP地址的格式 以及 网段地址等
  • 原文地址:https://www.cnblogs.com/ecustlegendn324/p/13936152.html
Copyright © 2011-2022 走看看