Problem:
MinimumCostPath

NxNの方眼がある。

(N=3の場合の図)

隣接するマス目に移動するにはコストが1かかる。ただし、斜めに移動することは出来ない。
また障害物があるマス目がM個あり、そのマスに入ることは許されない。
マス(1, 1)からマス(N, N)に最小のコストで移動する方法は何通りあるか。
答えは大きくなることがありうるので、1000000009(=109+9)でMODを取って出力せよ。

Input

入力は以下の形式で与えられる

N M
X1 Y1
X2 Y2
……
XM YM

Xi, Yiは(Xi, Yi)に障害物があることを表す

Constraints

2 ≤ N ≤ 106

0 ≤ M ≤ 50

1 ≤ Xi , Yi ≤ N

i ≠ jならば (Xi, Yi) ≠ (Xj, Yj)

(Xi, Yi) ≠ (1, 1)

(Xi, Yi) ≠ (N, N)

Output

1行に経路の総数を出力せよ。ただし、マス(1, 1)からマス(N, N)に移動する経路が存在しない場合は0と出力せよ。

Sample Input 1

3 0

Output for the Sample Input 1

6

以下の図に対応する。

Sample Input 2

3 1
2 2

Output for the Sample Input 2

2

以下の図に対応する。

Sample Input 3

5 8
4 3
2 1
4 2
4 4
3 4
2 2
2 4
1 4

Output for the Sample Input 3

1

以下の図に対応する。

Sample Input 4

1000 10
104 87
637 366
393 681
215 604
707 876
943 414
95 327
93 415
663 596
661 842

Output for the Sample Input 4

340340391

Sample Input 5

2 2
1 2
2 1

Output for the Sample Input 5

0

Solution in C++ (judge verdict: Wrong Answer)

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <utility>
#include <queue>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define mp make_pair
typedef long long Int;
#define MOD (1000000009LL)
#define INF (1<<28)

#define P (3000000)
int n, m;
pair<int, int> ps[64];
Int inv[P], fact[P], ifact[P];

Int f(int sx, int sy, int ex, int ey) {
    const int dx = ex-sx, dy = ey-sy;
    if (dx < 0 || dy < 0) return 0;
    return fact[dx+dy] * ifact[dx] % MOD * ifact[dy] % MOD;
}

Int calc(int sx, int sy, int ex, int ey) {
    static Int dp[64][2];
    rep (i, m) dp[i][0] = 0, dp[i][1] = f(sx, sy, ps[i].first, ps[i].second);
    Int ans = f(sx, sy, ex, ey);
    rep (i, m) for (int j = i+1; j < m; j++) rep (t, 2) {
        const Int w = dp[i][t] * f(ps[i].first, ps[i].second, ps[j].first, ps[j].second);
        dp[j][(t+1)%2] = (dp[j][(t+1)%2] + w) % MOD;
    }
    rep (i, m) rep (t, 2) {
        const Int w = dp[i][t] * f(ps[i].first, ps[i].second, ex, ey);
//        printf("[%d][%d], %d\n", i, t, (int)w);
        if (t) ans = (ans - w%MOD + MOD) % MOD;
        else ans = (ans + w) % MOD;
    }
    return ans;
}

const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
#define D (128)
int xof[2][D][D], yof[2][D][D], dist[2][D][D];
Int cnt[2][D][D][5];

void build(int w, int L) {
    queue<pair<int, int> > q;
    q.push(mp(0, 0));
    memset(dist[w], -1, sizeof(dist[0]));
    dist[w][0][0] = 0;
    rep (x, L) rep (y, L) {
        if (w == 0) xof[w][x][y] = x, yof[w][x][y] = y;
        else xof[w][x][y] = n-1-x, yof[w][x][y] = n-1-y;
    }
    rep (x, L) rep (y, L) rep (i, m) {
        if (xof[w][x][y] == ps[i].first && yof[w][x][y] == ps[i].second) {
            dist[w][x][y] = INF;
        }
    }
    while (!q.empty()) {
        const pair<int, int> vv = q.front();
        q.pop();
        const int x = vv.first, y = vv.second;
        rep (d, 4) {
            const int nx = x+dx[d], ny = y+dy[d];
            if (nx >= 0 && nx < L && ny >= 0 && ny < L
                    && dist[w][nx][ny] < INF) {
                if (dist[w][nx][ny] == -1) {
                    q.push(mp(nx, ny));
                    dist[w][nx][ny] = dist[w][x][y] + 1;
                }
            }
        }
    }
    rep (x, L) rep (y, L) if (dist[w][x][y] == -1) dist[w][x][y] = INF;
    vector<pair<int, pair<int, int> > > vs;
    rep (x, L) rep (y, L) if (dist[w][x][y] < INF) {
        vs.push_back(mp(dist[w][x][y], mp(x, y)));
    }
    sort(vs.begin(), vs.end());
    memset(cnt[w], 0, sizeof(cnt[0]));
    cnt[w][0][0][4] = 1;
    /*
    rep (i, L) rep (j, L) {
        if (dist[w][i][j] < INF) printf("%d%c", dist[w][i][j], "\n "[j+1<L]);
        else printf("-%c", "\n "[j+1<L]);
    }
    */
    rep (i, vs.size()) rep (t, 5) {
        const int x = vs[i].second.first, y = vs[i].second.second;
        rep (d, 4) {
            const int nx = x+dx[d], ny = y+dy[d];
            if (nx >= 0 && nx < L && ny >= 0 && ny < L
                    && dist[w][nx][ny] < INF) {
                if (dist[w][nx][ny] == dist[w][x][y] + 1) {
                    cnt[w][nx][ny][d] = (cnt[w][nx][ny][d] + cnt[w][x][y][t]) % MOD;
                }
            }
        }
    }
}

int main() {
    inv[1] = 1;
    for (int i = 2; i < P; i++) inv[i] = inv[MOD%i] * (MOD - MOD/i) % MOD;
    fact[0] = ifact[0] = 1;
    rep (i, P-1) {
        fact[i+1] = (i+1)*fact[i]%MOD;
        ifact[i+1] = inv[i+1]*ifact[i]%MOD;
    }
    scanf("%d%d", &n, &m);
    rep (i, m) scanf("%d%d", &ps[i].first, &ps[i].second);
    rep (i, m) ps[i].first--, ps[i].second--;
    sort(ps, ps+m);
//    cout << f(0, 0, n-1, n-1) << endl;
//    cout << calc(0, 0, n-1, n-1) << endl;
    if (n < D) {
        build(0, n);
        cout << cnt[0][n-1][n-1][0] + cnt[0][n-1][n-1][1] << endl;
        return 0;
//        return 0;
    }
    const int L = 55;
    build(0, L);
    build(1, L);
    Int ans = 0;
    int cur = INF;
    vector<pair<int, int> > vs;
    rep (i, L) rep (j, L) if (dist[0][i][j] < INF) {
        Int c = (cnt[0][i][j][2] + cnt[0][i][j][3] + cnt[0][i][j][4]) % MOD;
        if (c != 0) {
//            printf("%d, %d\n", i, j);
            vs.push_back(mp(i, j));
        }
    }
    rep (i, L) rep (j, L) if (dist[1][i][j] < INF) {
        Int c = (cnt[1][i][j][2] + cnt[1][i][j][3] + cnt[1][i][j][4]) % MOD;
        if (c == 0) continue;
        rep (k, vs.size()) {
            const int x = vs[k].first, y = vs[k].second;;
            Int w = calc(xof[0][x][y], yof[0][x][y], xof[1][i][j], yof[1][i][j]);
            if (w == 0) continue;
            int sum = 0;
            sum += dist[0][x][y];
            sum += dist[1][i][j];
            sum += xof[1][i][j] - xof[0][x][y];
            sum += yof[1][i][j] - yof[0][x][y];
            if (cur > sum) {
                cur = sum, ans = 0;
//                cout << calc(x, y, xof[1][i][j], yof[1][i][j]) << endl;
            }
            if (cur == sum) {
//            printf("(%d, %d) -> (%d, %d), %d, %d\n", xof[0][x][y], yof[0][x][y], xof[1][i][j], yof[1][i][j], dist[0][x][y], dist[1][i][j]);
        Int c0 = (cnt[0][x][y][2] + cnt[0][x][y][3] + cnt[0][x][y][4]) % MOD;
        /*
        cout << "c0 = "  << c0 << endl;
        cout << "c = " << c << endl;
        cout << "w = " << w << endl;
        */
                ans = (ans + c * w % MOD * c0) % MOD;
            }
        }
    }
    cout << ans << endl;
    return 0;
}