[题目链接]
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; }