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

#include <bits/stdc++.h>

using namespace std;
#define int long long

typedef int number;
typedef vector<number> Array;
typedef vector<Array> matrix;

const int mod = 1000000009;

// O( n )
matrix identity(int n) {
  matrix A(n, Array(n));
  for (int i = 0; i < n; ++i)
    A[i][i] = 1;
  return A;
}
// O( n^2 )
Array mul(const matrix &A, const Array &x) {
  Array y(A.size());
  for (int i = 0; i < A.size(); ++i)
    for (int j = 0; j < A[0].size(); ++j)
      y[i] = (y[i] + A[i][j] * x[j]) % mod;
  return y;
}
// O( n^3 )
matrix mul(const matrix &A, const matrix &B) {
  matrix C(A.size(), Array(B[0].size()));
  for (int i = 0; i < C.size(); ++i)
    for (int j = 0; j < C[i].size(); ++j)
      for (int k = 0; k < A[i].size(); ++k)
        C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
  return C;
}
// O( n^3 log e )
matrix pow(const matrix &A, int e) {
  return e == 0       ? identity(A.size())
         : e % 2 == 0 ? pow(mul(A, A), e / 2)
                      : mul(A, pow(A, e - 1));
}

#define range(i, x, y)                                                         \\
  i = (x);                                                                     \\
  i < (y);                                                                     \\
  i++
#define rep(i, n) for (int i = 0, i##_len = n; i < i##_len; i++)
#define all(x) begin(x), end(x)
#define lim(x, r, l) (r <= x && x < l)
typedef long long ll;
typedef long double ld;

signed main() {
  int w, h, n;
  int num = 1;
  while (cin >> w >> h >> n, w != 0) {
    map<int, vector<int>> obst;
    rep(i, n) {
      int x, y;
      cin >> x >> y;
      if (obst.find(y) == obst.end()) {
        obst[y] = vector<int>{x};
      } else {
        obst[y].push_back(x);
      }
    }
    if (obst.find(h) == obst.end()) {
      obst[h] = vector<int>{1};
    }
    Array res(w);
    res[0] = 1;

    matrix way(w, Array(w));
    rep(i, w) {
      if (i - 1 >= 0)
        way[i][i - 1] = 1;
      way[i][i] = 1;
      if (i + 1 < w)
        way[i][i + 1] = 1;
    }

    int prv = 1;
    for (auto ob : obst) {
      int y;
      vector<int> xs;
      tie(y, xs) = ob;
      res = mul(pow(way, y - prv), res);
      for (int x : xs) {
        res[x - 1] = 0;
      }
      prv = y;
    }
    cout << "Case " << num << ": " << res[w - 1] << endl;
    num++;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#include <cassert>

namespace detail {

bool is_zero(double d) { return (std::abs(d) < 1e-9); }
bool is_zero(long double d) { return (std::abs(d) < 1e-9); }

} // namespace detail

template <typename T> class matrix {
public:
  matrix() = delete;
  matrix(int r, int c) : v_(r, std::vector<T>(c)), row_(r), column_(c) {}
  matrix(std::vector<std::vector<T>> const &v)
      : v_(v), row_(v.size()), column_((v.size() == 0 ? 0 : v[0].size())) {}
  matrix(matrix const &) = default;
  matrix(matrix &&) = default;
  matrix &operator=(matrix const &) = default;
  matrix &operator=(matrix &&) = default;
  ~matrix() = default;

  std::vector<T> &operator[](unsigned int i) { return v_[i]; }
  const std::vector<T> &operator[](unsigned int i) const { return v_[i]; }
  matrix &operator+=(matrix const &other) {
    assert("matrix operator+: row or column size does not match" &&
           other.row_size() == row_ && other.column_size() == column_);

    for (int i = 0; i < row_; ++i) {
      for (int j = 0; j < column_; ++j) {
        v_[i][j] += other[i][j];
      }
    }
    return *this;
  }
  matrix &operator-=(matrix const &other) {
    assert("matrix operator-: row or column size does not match" &&
           other.row_size() == row_ && other.column_size() == column_);

    for (int i = 0; i < row_; ++i) {
      for (int j = 0; j < column_; ++j) {
        v_[i][j] -= other[i][j];
      }
    }
    return *this;
  }

  bool operator==(matrix const &rhs) const {
    if (row_ != rhs.row_size() || column_ != rhs.column_size()) {
      return false;
    }
    for (int i = 0; i < row_; ++i) {
      for (int j = 0; j < column_; ++j) {
        if (std::abs(v_[i][j] - rhs[i][j]) > 1e-9) {
          return false;
        }
      }
    }
    return true;
  }
  bool operator!=(matrix const &rhs) { return !(*this == rhs); }

  int row_size() const { return row_; }
  int column_size() const { return column_; }

  // for debug
  void print() {
    for (int i = 0; i < row_; ++i) {
      for (int j = 0; j < column_; ++j) {
        std::cout << v_[i][j];
        if (j != column_ - 1) {
          std::cout << " ";
        }
      }
      std::cout << std::endl;
    }
  }

private:
  std::vector<std::vector<T>> v_;
  int row_, column_;
};

template <typename T> matrix<T> operator-(matrix<T> m) {
  for (int i = 0; i < m.row_size(); ++i) {
    for (int j = 0; j < m.column_size(); ++j) {
      m[i][j] = -m[i][j];
    }
  }
}

template <typename T> matrix<T> operator+(matrix<T> lhs, matrix<T> const &rhs) {
  lhs += rhs;
  return lhs;
}

template <typename T> matrix<T> operator-(matrix<T> lhs, matrix<T> const &rhs) {
  lhs -= rhs;
  return lhs;
}

template <typename T>
matrix<T> operator*(matrix<T> const &lhs, matrix<T> const &rhs) {
  assert("matrix operator*: lhs.column_size() != rhs.row_size()" &&
         lhs.column_size() == rhs.row_size());

  matrix<T> ret(lhs.row_size(), rhs.column_size());
  for (int i = 0; i < ret.row_size(); ++i) {
    for (int k = 0; k < lhs.column_size(); ++k) {
      for (int j = 0; j < ret.column_size(); ++j) {
        ret[i][j] += lhs[i][k] * rhs[k][j];
      }
    }
  }
  return ret;
}

template <typename T> matrix<T> transpose(matrix<T> const &m) {
  const int R = m.row_size(), C = m.column_size();
  matrix<T> ret(C, R);
  for (int i = 0; i < C; ++i) {
    for (int j = 0; j < R; ++j) {
      ret[i][j] = m[j][i];
    }
  }
  return ret;
}

// verified
template <typename T> int rank_matrix(matrix<T> a) {
  const int r = a.row_size(), c = a.column_size();
  matrix<long double> b(r, c);
  for (int i = 0; i < r; ++i) {
    for (int j = 0; j < c; ++j) {
      b[i][j] = static_cast<long double>(a[i][j]);
    }
  }
  return rank_matrix<long double>(std::move(b));
}

template <> int rank_matrix(matrix<long double> a) {
  const int R = a.row_size(), C = a.column_size();
  int r = 0;
  for (int i = 0; i < C && r < R; ++i) {
    int pivot = r;
    for (int j = r + 1; j < R; ++j) {
      if (std::abs(a[j][i]) > std::abs(a[pivot][i])) {
        pivot = j;
      }
    }
    std::swap(a[pivot], a[r]);
    if (detail::is_zero(a[r][i])) {
      continue;
    }
    for (int k = C - 1; k >= i; --k) {
      a[r][k] = a[r][k] / a[r][i];
    }
    for (int j = r + 1; j < R; ++j) {
      for (int k = C - 1; k >= i; --k) {
        a[j][k] += -a[r][k] * a[j][i];
      }
    }
    ++r;
  }
  return r;
}

// todo: only long double?
template <typename T> T det(matrix<T> a) {
  const int R = a.row_size(), C = a.column_size();
  matrix<long double> b(R, C);
  for (int i = 0; i < R; ++i) {
    for (int j = 0; j < C; ++j) {
      b[i][j] = static_cast<long double>(a[i][j]);
    }
  }
  return static_cast<T>(det<long double>(std::move(b)));
}
template <> long double det(matrix<long double> a) {
  assert("det(): matrix is not square." && a.column_size() == a.row_size());
  const int R = a.row_size(), C = a.column_size();
  long double ret = 1.0;
  for (int i = 0; i < R; ++i) {
    int pivot = i;
    for (int j = i + 1; j < R; ++j) {
      if (std::abs(a[j][i]) > std::abs(a[pivot][i])) {
        pivot = j;
      }
    }
    std::swap(a[pivot], a[i]);
    ret *= a[i][i] * (i != pivot ? -1.0 : 1.0);
    if (detail::is_zero(a[i][i])) {
      break;
    }
    for (int j = i + 1; j < R; ++j) {
      for (int k = C - 1; k >= i; --k) {
        a[j][k] -= a[i][k] * a[j][i] / a[i][i];
      }
    }
  }
  return ret;
}

template <typename T> matrix<T> eye(int n) {
  matrix<T> res(n, n);
  for (int i = 0; i < n; ++i) {
    res[i][i] = 1;
  }
  return res;
}

// mulptile mod ver
template <typename T>
matrix<T> mul(matrix<T> const &a, matrix<T> const &b, long long M) {
  int R = a.row_size(), C = b.column_size();
  assert("matrix mul: row and column size does not match" &&
         a.column_size() == b.row_size());
  matrix<T> ret(R, C);
  for (int i = 0; i < R; ++i) {
    for (int k = 0; k < a.column_size(); ++k) {
      for (int j = 0; j < C; ++j) {
        ret[i][j] = (ret[i][j] + ((a[i][k] * b[k][j]) % M)) % M;
      }
    }
  }
  return ret;
}

template <typename T> matrix<T> pow(matrix<T> x, long long y) {
  assert("matrix pow: matrix is not square" && x.column_size() == x.row_size());
  matrix<T> ret = eye<T>(x.column_size());
  while (y > 0) {
    if (y & 1) {
      ret = ret * x;
    }
    x = x * x;
    y >>= 1;
  }
  return ret;
}

template <typename T> matrix<T> modpow(matrix<T> x, long long y, long long M) {
  assert("matrix pow: matrix is not square" && x.column_size() == x.row_size());
  matrix<T> ret = eye<T>(x.column_size());
  while (y > 0) {
    if (y & 1) {
      ret = mul(ret, x, M);
    }
    x = mul(x, x, M);
    y >>= 1;
  }
  return ret;
}

#define int long long
#define range(i, x, y)                                                         \\
  i = (x);                                                                     \\
  i < (y);                                                                     \\
  i++
#define rep(i, n) for (int i = 0, i##_len = n; i < i##_len; i++)
#define all(x) begin(x), end(x)
#define lim(x, r, l) (r <= x && x < l)
typedef long long ll;
typedef long double ld;
using namespace std;

const int mod = 1000000009;

signed main() {
  int w, h, n;
  while (cin >> w >> h >> n, w != 0) {
    map<int, vector<int>> obst;
    rep(i, n) {
      int x, y;
      cin >> x >> y;
      if (obst.find(y) == obst.end()) {
        obst[y] = vector<int>{x};
      } else {
        obst[y].push_back(x);
      }
    }
    obst[h] = vector<int>{1};

    matrix<int> res(w, 1);
    res[0][0] = 1;
    matrix<int> way(w, w);
    rep(i, w) {
      if (i - 1 >= 0)
        way[i][i - 1] = 1;
      way[i][i] = 1;
      if (i + 1 < w)
        way[i][i + 1] = 1;
    }

    int prv = 1;
    for (auto ob : obst) {
      int y;
      vector<int> xs;
      tie(y, xs) = ob;
      res = mul(modpow(way, y - prv, mod), res, mod);
      for (int x : xs) {
        res[x - 1][0] = 0;
      }
      cout << "==" << y << endl;
      res.print();
      prv = y;
    }

    cout << res[w - 1][0] << endl;
  }
}