[Codeforces 559C] Gerald and Giant Chess

[题目链接]

         http://codeforces.com/contest/559/problem/C

[算法]

        f[i]表示经过(Xi,Yi)且不经过其它黑色格子的路径总数

        那么有 : f[i] = C(Xi + Yi - 2,Xi - 1) - sigma( f[j] * C(Xi - Xj + Yi - Yj,Xi - Xj) ) (Xi >= Xj,Yi >= Yj)

        预处理阶乘,阶乘逆元,即可

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 2010
const int MAXH = 1e5 + 10;
const int P = 1e9 + 7;

struct info
{
    int x,y;
} a[MAXN];

int i,j,h,w,n;
int f[MAXN];
int fac[MAXH << 1],inv[MAXH << 1];

inline bool cmp(info a,info b)
{
    return a.x == b.x ? a.y < b.y : a.x < b.x;
}
inline int power(int a,int n)
{
    int i;
    int res = 1,b = a;
    while (n > 0)
    {
        if (n & 1) res = 1ll * res * b % P;
        b = 1ll * b * b % P;
        n >>= 1;
    }
    return res;
}
inline void init()
{
    int i;
    fac[0] = 1;
    for (i = 1; i < MAXH << 1; i++) fac[i] = 1ll * fac[i-1] * i % P;
    inv[(MAXH << 1) - 1] = power(fac[(MAXH << 1) - 1],P - 2);
    for (i = (MAXH << 1) - 2; i >= 0; i--) inv[i] = 1ll * inv[i+1] * (i + 1) % P;
}
inline int C(int x,int y)
{
    return 1ll * fac[x] * inv[y] % P * inv[x-y] % P;
}
int main()
{
    
    init();
    scanf("%d%d%d",&h,&w,&n);
    for (i = 1; i <= n; i++) scanf("%d%d",&a[i].x,&a[i].y);
    n++;
    a[n].x = h; a[n].y = w;
    sort(a+1,a+n+1,cmp);
    for (i = 1; i <= n + 1; i++)
    {
        f[i] = C(a[i].x + a[i].y - 2,a[i].x - 1);
        for (j = i - 1; j >= 1; j--)
        {
            if (a[i].x >= a[j].x && a[i].y >= a[j].y)
                f[i] = ((f[i] - 1ll * f[j] * C(a[i].x - a[j].x + a[i].y - a[j].y,a[i].x  - a[j].x)) % P + P) % P;
        }
    }
    printf("%d
",f[n]);
    
    return 0;
}
原文地址:https://www.cnblogs.com/evenbao/p/9340571.html