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

#include <bits/stdc++.h>
using namespace std;

typedef long long lli;
typedef vector<lli> vec;
typedef vector<vec> mat;

struct P {
  lli x, y;
  bool operator<(const P &p) const { return y == p.y ? x < p.x : y < p.y; }
};

const lli MOD = 1000000009;

lli modmul(lli a, lli b) {
  return (((a * (b >> 20) % MOD) << 20) + a * (b & ((1 << 20) - 1))) % MOD;
}

void mul(const mat &a, const mat &b, mat &c) {
  int n = a.size();

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      c[i][j] = 0;
      for (int k = 0; k < n; k++) {
        c[i][j] = (c[i][j] + modmul(a[i][k], b[k][j])) % MOD;
      }
    }
  }
}

vec mul(const vec &a, const mat &b) {
  int n = a.size();
  vec c(n, 0);

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      c[i] = (c[i] + modmul(a[j], b[j][i])) % MOD;
    }
  }

  return c;
}

lli w, h;
int n;
P v[30];

void init_a(mat &a, mat a_pow[65]) {
  a.assign(w, vec(w, 0));
  for (int i = 0; i < w; i++) {
    if (i - 1 >= 0)
      a[i][i - 1] = 1;
    a[i][i] = 1;
    if (i + 1 < w)
      a[i][i + 1] = 1;
  }

  a_pow[0].assign(w, vec(w, 0));
  a_pow[1] = a;
  for (int i = 0; i < w; i++)
    a_pow[0][i][i] = 1;
  for (int i = 2; i < 65; i++) {
    a_pow[i].assign(w, vec(w, 0));
    mul(a_pow[i - 1], a_pow[i - 1], a_pow[i]);
  }
}

mat pow(mat a, lli p, mat a_pow[65]) {
  int n = a.size(), j = 0;
  mat C[2] = {mat(n, vec(n, 0)), mat(n, vec(n, 0))};

  for (int i = 0; i < n; i++)
    C[0][i][i] = 1;

  for (int i = 1; i < 65; i++) {
    if (p <= 0)
      break;
    if (p & 1) {
      mul(a_pow[i], C[j & 1], C[!(j & 1)]);
      j = !j;
    }
    p >>= 1;
  }

  return C[j & 1];
}

lli solve() {
  lli pos = 1;
  int v_pos = 0;
  vec b(w, 0);
  vector<lli> obst_y;
  mat a;
  mat a_pow[65];

  init_a(a, a_pow);
  b[0] = 1;

  sort(v, v + n);
  for (int i = 0; i < n; i++) {
    if (v[i].y == 1) {
      v_pos++;
      continue;
    }
    if (obst_y.size() == 0 || obst_y[obst_y.size() - 1] != v[i].y) {
      obst_y.push_back(v[i].y);
    }
  }

  for (int i = 0; i < obst_y.size(); i++) {
    b = mul(b, pow(a, obst_y[i] - pos, a_pow));
    for (; v_pos < n; v_pos++) {
      if (v[v_pos].y != obst_y[i])
        break;
      b[v[v_pos].x - 1] = 0;
    }
    pos = obst_y[i];
  }
  b = mul(b, pow(a, h - pos, a_pow));

  return b[w - 1];
}

int main() {
  int cnt = 1;

  while (1) {
    scanf("%lld%lld%d", &w, &h, &n);
    if (w == 0 && h == 0)
      break;
    for (int i = 0; i < n; i++) {
      P p;
      scanf("%lld%lld", &p.x, &p.y);
      v[i] = p;
    }
    printf("Case %d: %lld\\n", cnt++, solve());
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

typedef long long lli;
typedef vector<lli> vec;
typedef vector<vec> mat;

struct P {
  lli x, y;
  bool operator<(const P &p) const { return y == p.y ? x < p.x : y < p.y; }
};

const lli MOD = 1000000009;

lli modmul(lli a, lli b) {
  return (((a * (b >> 20) % MOD) << 20) + a * (b & ((1 << 20) - 1))) % MOD;
}

void mul(const mat &a, const mat &b, mat &c) {
  int n = a.size();
  // mat c(n, vec(n, 0));

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      c[i][j] = 0;
      for (int k = 0; k < n; k++) {
        c[i][j] = (c[i][j] + modmul(a[i][k], b[k][j])) % MOD;
      }
    }
  }

  // return c;
}

vec mul(const vec &a, const mat &b) {
  int n = a.size();
  vec c(n, 0);

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      c[i] = (c[i] + modmul(a[j], b[j][i])) % MOD;
    }
  }

  return c;
}

mat pow(mat a, lli p) {
  int n = a.size(), i = 0, j = 0;
  mat C[2] = {mat(n, vec(n, 0)), mat(n, vec(n, 0))}, A[2] = {a, a};

  for (int i = 0; i < n; i++)
    C[0][i][i] = 1;
  while (p > 0) {
    if (p % 2 == 1) {
      // c = mul(A[i%2], c);
      mul(A[i % 2], C[j % 2], C[!(j % 2)]);
      j = !j;
    }
    // a = mul(a, a);
    mul(A[i % 2], A[i % 2], A[!(i % 2)]);
    i = !i;
    p >>= 1;
  }

  return C[j % 2];
}

lli w, h, n;
vector<P> v;

int solve() {
  lli pos = 1;
  int v_pos = 0;
  mat a(w, vec(w, 0));
  vec b(w, 0);
  vector<lli> obst_y;

  b[0] = 1;
  for (int i = 0; i < w; i++) {
    if (i - 1 >= 0)
      a[i][i - 1] = 1;
    a[i][i] = 1;
    if (i + 1 < w)
      a[i][i + 1] = 1;
  }

  sort(v.begin(), v.end());
  for (int i = 0; i < n; i++) {
    if (v[i].y == 1) {
      v_pos++;
      continue;
    }
    if (obst_y.size() == 0 || obst_y[obst_y.size() - 1] != v[i].y) {
      obst_y.push_back(v[i].y);
    }
  }

  for (int i = 0; i < obst_y.size(); i++) {
    vec b2(w, 0);
    b = mul(b, pow(a, obst_y[i] - pos - 1));
    for (int j = 0; j < w; j++) {
      if (v_pos < v.size() && v[v_pos].y == obst_y[i] && v[v_pos].x - 1 == j) {
        v_pos++;
        continue;
      }
      if (j - 1 >= 0)
        b2[j] = (b2[j] + b[j - 1]) % MOD;
      b2[j] = (b2[j] + b[j]) % MOD;
      if (j + 1 < w)
        b2[j] = (b2[j] + b[j + 1]) % MOD;
    }
    b = b2;
    pos = obst_y[i];
  }
  b = mul(b, pow(a, h - pos));

  return b[w - 1];
}

int main() {
  int cnt = 1;
  while (cin >> w >> h >> n && (w | h)) {
    v.clear();
    for (int i = 0; i < n; i++) {
      P p;
      cin >> p.x >> p.y;
      v.push_back(p);
    }
    cout << "Case " << cnt++ << ": " << solve() << endl;
  }
}