码迷,mamicode.com
首页 > 其他好文 > 详细

[Codeforces 559C] Gerald and Giant Chess

时间:2021-05-23 23:32:23      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:node   c++   its   题意   mod   直接   get   code   long   

https://codeforces.ml/contest/559/problem/C

题意:
从矩阵的左上角走到右下角,其中\(n\)个格子不能走,每次只能向右走或者向下走,问方案数。矩阵大小\(10^5 \times 10^5\)\(1 \leq n \leq 2000\)

思路:
矩阵大小太大了,不能用常规方法去写。不能走的格子的数量很小,尝试从其中入手。

对于一个格子来说,它对答案的贡献是\((1\), \(1)\)到它的方案数 \(\times\) 它到\((h\), \(w)\)的方案数,但是发现左上的格子对于右下的格子是有影响的,因为左上的格子能走到右下的格子,我们在减去左上格子的贡献后,如果在减去右下格子的贡献时仍这样计算,就会重复计数。然后发现重复的部分时很容易计算的,将左上的格子作为中心点,计算出\((1\), \(1)\)到左上格子的方案,再计算左上格子到右下格子的方案,两个乘一下就是先前已经计算进去的贡献了,减掉即可。

有了解题思路,那么就先记录下不能走的格子的坐标,排个序,优先处理左上的格子。存在大量重复运算,用\(dp\)数组记录一下方案数,减少时间复杂度。计算组合数也要直接算,不要一个个慢慢乘。取模的时候要注意负数的情况。

#include <bits/stdc++.h>

using namespace std;

inline int rd() {
    int f = 0; int x = 0; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) f |= (ch == ‘-‘);
    for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘;
    if (f) x = -x;
    return x;
}

typedef long long ll;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 7;
const ll mod = 1e9 + 7;

int h, w, n;
ll inv[N];
int dp[N];

ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

void chmod(ll &a) {
    while (a < 0) a += mod;
    while (a >= mod) a-= mod;
}

struct Node {
    int x, y;
    bool operator < (const Node &a) const {
        if (x == a.x) return y < a.y;
        return x < a.x;
    }
}node[N];

void init() {
    inv[0] = 1;
    inv[1] = 1;
    for (int i = 2; i < N; ++i) {
        inv[i] = inv[i - 1] * (ll)i % mod;
    }
}

ll C(int n, int m) {
    return inv[n] * powmod(inv[m] * inv[n - m], mod - 2) % mod;
}

void solve() {
    h = rd(); w = rd(); n = rd();
    ll ans = C(h + w - 2, h - 1);
    for (int i = 1; i <= n; ++i) {
        node[i].x = rd();
        node[i].y = rd();
    }
    sort(node + 1, node + 1 + n);
    for (int i = 1; i <= n; ++i) {
        int x = node[i].x, y = node[i].y;;
        ll tmp = C(x + y - 2, x - 1);
        for (int j = 1; j < i; ++j) {
            int px = node[j].x, py = node[j].y;
            if (px <= x && py <= y) {
                tmp -= C(x - px + y - py, x - px) * dp[j] % mod;
                chmod(tmp);
            }
        }
        dp[i] = tmp;
        tmp = tmp * C(h - x + w - y, h - x) % mod;
        ans -= tmp;
        chmod(ans);
    }
    printf("%lld\n", ans);
}

int main() {
    int t = 1;
    init();
    while (t--) solve();
    return 0;
}

[Codeforces 559C] Gerald and Giant Chess

标签:node   c++   its   题意   mod   直接   get   code   long   

原文地址:https://www.cnblogs.com/Sstee1XD/p/14728197.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!