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

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

namespace libcomp {
namespace math {

template <typename T> class Matrix {

private:
  int N, M;
  vector<vector<T>> data;

  template <typename _Func> Matrix<T> apply(_Func f) const {
    Matrix<T> ret(N, M);
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < M; ++j) {
        ret(i, j) = f(data[i][j]);
      }
    }
    return ret;
  }

  template <typename _Func> Matrix<T> apply_scalar(const T &s, _Func f) const {
    return apply(bind2nd(f, s));
  }

  template <typename _Func>
  Matrix<T> apply_mat(const Matrix<T> &m, _Func f) const {
    assert(N == m.N && M == m.M);
    Matrix<T> ret(N, M);
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < M; ++j) {
        ret(i, j) = f(data[i][j], m(i, j));
      }
    }
    return ret;
  }

public:
  Matrix(int N, int M) : N(N), M(M), data(N, vector<T>(M)) {}

  int rows() const { return N; }
  int columns() const { return M; }

  const T &operator()(int i, int j) const { return data[i][j]; }
  T &operator()(int i, int j) { return data[i][j]; }

  Matrix<T> operator-() const { return apply(negate<T>()); }

  Matrix<T> operator+(const T &s) const { return apply_scalar(s, plus<T>()); }
  Matrix<T> &operator+=(const T &s) { return *this = *this + s; }

  Matrix<T> operator-(const T &s) const { return apply_scalar(s, minus<T>()); }
  Matrix<T> &operator-=(const T &s) { return *this = *this - s; }

  Matrix<T> operator*(const T &s) const {
    return apply_scalar(s, multiplies<T>());
  }
  Matrix<T> &operator*=(const T &s) { return *this = *this * s; }

  Matrix<T> operator/(const T &s) const {
    return apply_scalar(s, divides<T>());
  }
  Matrix<T> &operator/=(const T &s) { return *this = *this / s; }

  Matrix<T> operator%(const T &s) const {
    return apply_scalar(s, modulus<T>());
  }
  Matrix<T> &operator%=(const T &s) { return *this = *this % s; }

  Matrix<T> operator+(const Matrix<T> &m) const {
    return apply_mat(m, plus<T>());
  }
  Matrix<T> &operator+=(const Matrix<T> &m) { return *this = *this + m; }

  Matrix<T> operator-(const Matrix<T> &m) const {
    return apply_mat(m, minus<T>());
  }
  Matrix<T> &operator-=(const Matrix<T> &m) { return *this = *this - m; }

  Matrix<T> operator*(const Matrix<T> &m) const {
    assert(M == m.N);
    Matrix<T> ret(N, m.M);
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < m.M; ++j) {
        for (int k = 0; k < M; ++k) {
          ret(i, j) += data[i][k] * m(k, j);
        }
      }
    }
    return ret;
  }
  Matrix<T> &operator*=(const Matrix<T> &m) { return *this = *this * m; }
};

template <typename T> ostream &operator<<(ostream &os, const Matrix<T> &m) {
  for (int i = 0; i < m.rows(); ++i) {
    for (int j = 0; j < m.columns(); ++j) {
      os << m(i, j) << "\\t";
    }
    os << endl;
  }
  return os;
}

} // namespace math
} // namespace libcomp

using libcomp::math::Matrix;

Matrix<ll> modpow(const Matrix<ll> &m, ll y, ll mod) {
  if (y == 1) {
    return m;
  }
  Matrix<ll> t = modpow(m, y / 2, mod);
  t *= t;
  for (int i = 0; i < t.rows(); ++i) {
    for (int j = 0; j < t.columns(); ++j) {
      t(i, j) %= mod;
    }
  }
  if (y % 2 == 1) {
    t *= m;
    for (int i = 0; i < t.rows(); ++i) {
      for (int j = 0; j < t.columns(); ++j) {
        t(i, j) %= mod;
      }
    }
  }
  return t;
}

int main() {
  ios_base::sync_with_stdio(false);
  while (true) {
    int n, m, a, b, c, t;
    cin >> n >> m >> a >> b >> c >> t;
    if (n == 0) {
      break;
    }
    Matrix<ll> mat(n, n);
    for (int i = 0; i < n; ++i) {
      if (i > 0) {
        mat(i, i - 1) = a;
      }
      mat(i, i) = b;
      if (i + 1 < n) {
        mat(i, i + 1) = c;
      }
    }
    Matrix<ll> vec(n, 1);
    for (int i = 0; i < n; ++i) {
      cin >> vec(i, 0);
    }
    if (t > 0) {
      vec = modpow(mat, t, m) * vec;
    }
    for (int i = 0; i < n; ++i) {
      if (i != 0) {
        cout << " ";
      }
      cout << vec(i, 0) % m;
    }
    cout << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

namespace libcomp {
namespace math {

template <typename T> class Matrix {

private:
  int N, M;
  vector<vector<T>> data;

  template <typename _Func> Matrix<T> apply(_Func f) const {
    Matrix<T> ret(N, M);
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < M; ++j) {
        ret(i, j) = f(data[i][j]);
      }
    }
    return ret;
  }

  template <typename _Func> Matrix<T> apply_scalar(const T &s, _Func f) const {
    return apply(bind2nd(f, s));
  }

  template <typename _Func>
  Matrix<T> apply_mat(const Matrix<T> &m, _Func f) const {
    assert(N == m.N && M == m.M);
    Matrix<T> ret(N, M);
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < M; ++j) {
        ret(i, j) = f(data[i][j], m(i, j));
      }
    }
    return ret;
  }

public:
  Matrix(int N, int M) : N(N), M(M), data(N, vector<T>(M)) {}

  int rows() const { return N; }
  int columns() const { return M; }

  const T &operator()(int i, int j) const { return data[i][j]; }
  T &operator()(int i, int j) { return data[i][j]; }

  Matrix<T> operator-() const { return apply(negate<T>()); }

  Matrix<T> operator+(const T &s) const { return apply_scalar(s, plus<T>()); }
  Matrix<T> &operator+=(const T &s) { return *this = *this + s; }

  Matrix<T> operator-(const T &s) const { return apply_scalar(s, minus<T>()); }
  Matrix<T> &operator-=(const T &s) { return *this = *this - s; }

  Matrix<T> operator*(const T &s) const {
    return apply_scalar(s, multiplies<T>());
  }
  Matrix<T> &operator*=(const T &s) { return *this = *this * s; }

  Matrix<T> operator/(const T &s) const {
    return apply_scalar(s, divides<T>());
  }
  Matrix<T> &operator/=(const T &s) { return *this = *this / s; }

  Matrix<T> operator%(const T &s) const {
    return apply_scalar(s, modulus<T>());
  }
  Matrix<T> &operator%=(const T &s) { return *this = *this % s; }

  Matrix<T> operator+(const Matrix<T> &m) const {
    return apply_mat(m, plus<T>());
  }
  Matrix<T> &operator+=(const Matrix<T> &m) { return *this = *this + m; }

  Matrix<T> operator-(const Matrix<T> &m) const {
    return apply_mat(m, minus<T>());
  }
  Matrix<T> &operator-=(const Matrix<T> &m) { return *this = *this - m; }

  Matrix<T> operator*(const Matrix<T> &m) const {
    assert(M == m.N);
    Matrix<T> ret(N, m.M);
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < m.M; ++j) {
        for (int k = 0; k < M; ++k) {
          ret(i, j) += data[i][k] * m(k, j);
        }
      }
    }
    return ret;
  }
  Matrix<T> &operator*=(const Matrix<T> &m) { return *this = *this * m; }
};

template <typename T> ostream &operator<<(ostream &os, const Matrix<T> &m) {
  for (int i = 0; i < m.rows(); ++i) {
    for (int j = 0; j < m.columns(); ++j) {
      os << m(i, j) << "\\t";
    }
    os << endl;
  }
  return os;
}

} // namespace math
} // namespace libcomp

using libcomp::math::Matrix;

Matrix<ll> modpow(const Matrix<ll> &m, ll y, ll mod) {
  if (y == 1) {
    return m;
  }
  Matrix<ll> t = modpow(m, y / 2, mod);
  t *= t;
  for (int i = 0; i < t.rows(); ++i) {
    for (int j = 0; j < t.columns(); ++j) {
      t(i, j) %= mod;
    }
  }
  if (y % 2 == 1) {
    t *= m;
    for (int i = 0; i < t.rows(); ++i) {
      for (int j = 0; j < t.columns(); ++j) {
        t(i, j) %= mod;
      }
    }
  }
  return t;
}

int main() {
  ios_base::sync_with_stdio(false);
  while (true) {
    int n, m, a, b, c, t;
    cin >> n >> m >> a >> b >> c >> t;
    Matrix<ll> mat(n, n);
    for (int i = 0; i < n; ++i) {
      if (i > 0) {
        mat(i, i - 1) = a;
      }
      mat(i, i) = b;
      if (i + 1 < n) {
        mat(i, i + 1) = c;
      }
    }
    Matrix<ll> vec(n, 1);
    for (int i = 0; i < n; ++i) {
      cin >> vec(i, 0);
    }
    if (t > 0) {
      vec = modpow(mat, t, m) * vec;
    }
    for (int i = 0; i < n; ++i) {
      if (i != 0) {
        cout << " ";
      }
      cout << vec(i, 0) % m;
    }
    cout << endl;
  }
  return 0;
}