Codeforces Round #313 (Div. 1) C. Gerald and Giant Chess DP

来源:互联网 发布:tensorflow 32位 编辑:程序博客网 时间:2024/06/07 00:02

题目链接:这里
题意:一个n*m的图,让你从左上角走到右下角,有一些点不能经过,问你有多少种方法
解法:令dp[i]表示从原点不经过任何坏点到第i个点的方案数

dp[i]=C(xi,xi+yi)sigma(dp[j]C(xixj,xixj+yiyj))

xj<=xi,yj<=yi

这里:这里写链接内容

//CF 559C#include <bits/stdc++.h>using namespace std;const int mod = 1e9+7;const int maxn = 1000010;#define ll long longstruct Point{    ll x, y;    Point(){}    Point(ll x, ll y) : x(x), y(y) {}    bool operator <(const Point &rhs) const{        if(x == rhs.x) return y < rhs.y;        return x < rhs.x;    }}p[5000];ll fac[maxn];ll powmod(ll a, ll b){    ll res = 1;    while(b){        if(b&1) res = res*a%mod;        a = a*a%mod;        b>>=1;    }    return res;}ll C(ll n, ll m){    if(m > n || m < 0) return 0;    ll s1 = fac[n], s2 = fac[m]*fac[n-m]%mod;    return s1*powmod(s2, mod-2)%mod;}ll dp[maxn];int n, m, k;int main(){    fac[0] = 1LL;    for(int i = 1; i < maxn; i++) fac[i] = fac[i-1] * i % mod;    scanf("%d%d%d", &n, &m, &k);    for(int i = 1; i <= k; i++){        scanf("%lld%lld", &p[i].x, &p[i].y);        p[i].x--, p[i].y--;    }    p[++k].x = n-1;    p[k].y = m-1;    sort(p+1, p+k+1);    for(int i = 1; i <= k; i++){        dp[i] = C(p[i].x + p[i].y, p[i].x);        for(int j = 1; j < i; j++){            if(p[j].y <= p[i].y){                dp[i] += (mod - dp[j]*C(p[i].x-p[j].x+p[i].y-p[j].y, p[i].x-p[j].x));                dp[i] %= mod;            }        }    }    printf("%lld\n", (dp[k]+mod)%mod);}
0 0