Problem p01559 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <iostream>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <utility>
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) {
        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]) % MOD << 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;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <iostream>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <utility>
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)

int n, m;
pair<int, int> ps[64];
Int inv[2000], fact[2000], ifact[2000];

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;
        }
      }
    }
  }
  vector<pair<int, pair<int, int>>> vs;
  rep(x, L) rep(y, L) if (dist[w][x][y] >= 0) {
    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 < 2000; i++)
    inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
  fact[0] = ifact[0] = 1;
  rep(i, 2000 - 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;
}