Problem p01511 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cassert>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <vector>
#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define fr(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); i++)
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define mp make_pair
#define dbg(x) cerr << #x << " = " << x << endl
using namespace std;

typedef vector<int> vi;
typedef long long ll;

const int inf = (int)1e9;
const double EPS = 1e-9, INF = 1e12;
const int mod = (int)1e9 + 9;

typedef vector<vi> M;
M operator*(const M &a, const M &b) {
  M res(a.size(), vi(b[0].size()));
  rep(i, res.size()) rep(j, res[0].size()) {
    rep(k, a[0].size()) res[i][j] = (res[i][j] + (ll)a[i][k] * b[k][j]) % mod;
  }
  return res;
}
vi operator*(const M &a, const vi &b) {
  vi res(a.size());
  rep(i, res.size()) rep(j, a[0].size()) res[i] =
      (res[i] + (ll)a[i][j] * b[j]) % mod;
  return res;
}
M pw[70];
ll w, h;
ll x[31], y[31], ys[31];
int n, dp[2][76];

void calc() {
  rep(i, w) if (dp[0][i] >= 0) for (int j = i - 1; j < i + 2; j++) {
    if (j < 0 || j >= w || dp[1][j] < 0)
      continue;
    (dp[1][j] += dp[0][i]) %= mod;
  }
}

int main() {
  int cs = 0;
  while (cin >> w >> h >> n, w) {
    rep(i, n) cin >> x[i] >> y[i], --x[i], ys[i] = --y[i];
    ys[n] = h;
    sort(ys, ys + n);

    pw[0] = M(w, vi(w));
    rep(i, w) {
      memset(dp, 0, sizeof(dp));
      dp[0][i] = 1;
      calc();
      rep(j, w) pw[0][i][j] = dp[1][j];
    }
    rep(i, 63) pw[i + 1] = pw[i] * pw[i];
    vi v(w);
    v[0] = 1;
    for (ll i = 0; i < h - 1; i++) {
      ll next = *lower_bound(ys, ys + n + 1, i);
      if (next > i + 1) {
        int k = 0;
        for (ll m = next - i - 1; m; m /= 2, k++)
          if (m & 1)
            v = pw[k] * v;
        i = next - 2;
        continue;
      }
      memset(dp, 0, sizeof(dp));
      rep(j, w) dp[0][j] = v[j];
      rep(j, n) if (i == y[j] || y[j] == i + 1) dp[y[j] - i][x[j]] = -1;
      calc();
      rep(j, w) v[j] = max(0, dp[1][j]);
    }
    printf("Case %d: %d\\n", ++cs, v[w - 1]);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <vector>
#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define fr(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); i++)
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define mp make_pair
#define dbg(x) cerr << #x << " = " << x << endl
using namespace std;

typedef vector<int> vi;
typedef long long ll;

const int inf = (int)1e9;
const double EPS = 1e-9, INF = 1e12;
const int mod = (int)1e9 + 9;

typedef vector<vi> M;
M operator*(const M &a, const M &b) {
  M res(a.size(), vi(b[0].size()));
  rep(i, res.size()) rep(j, res[0].size()) {
    rep(k, a[0].size())(res[i][j] += a[i][k] * a[k][j]) %= mod;
  }
  return res;
}
vi operator*(const M &a, const vi &b) {
  vi res(a.size());
  rep(i, res.size()) rep(j, a[0].size())(res[i] += a[i][j] * b[j]) %= mod;
  return res;
}
M pw[70];
int w, h, n;
int x[31], y[31], ys[31];
int dp[2][76];

void calc() {
  rep(i, w) if (dp[0][i] >= 0) for (int j = i - 1; j < i + 2; j++) {
    if (j < 0 || j >= w || dp[1][j] < 0)
      continue;
    dp[1][j] += dp[0][i];
  }
}

int main() {
  int cs = 0;
  while (cin >> w >> h >> n, w) {
    rep(i, n) cin >> x[i] >> y[i], --x[i], ys[i] = --y[i];
    ys[n] = h;
    sort(ys, ys + n);

    pw[0] = M(w, vi(w));
    rep(i, w) {
      memset(dp, 0, sizeof(dp));
      dp[0][0] = 1;
      calc();
      rep(j, w) pw[0][i][j] = dp[1][j];
    }
    rep(i, 63) pw[i + 1] = pw[i] * pw[i];
    vi v(w);
    v[0] = 1;
    for (ll i = 0; i < h - 1; i++) {
      int next = *lower_bound(ys, ys + n, i);
      if (next > i + 1) {
        int k = 0;
        for (ll m = next - i - 1; m; m /= 2, k++)
          if (m & 1)
            v = pw[k] * v;
        i = next - 2;
        continue;
      }
      memset(dp, 0, sizeof(dp));
      rep(j, w) dp[0][j] = v[j];
      rep(j, n) if (i == y[j] || y[j] == i + 1) dp[y[j] - i][x[j]] = -1;
      calc();
      rep(j, w) v[j] = max(0, dp[1][j]);
    }
    printf("Case %d: %d\\n", ++cs, v[w - 1]);
  }
  return 0;
}