Problem p03016 (C++)

Buggy submission (status: Runtime Error):
#include "bits/stdc++.h"
using namespace std;
#define LL long long
#define PB push_back
#define MP make_pair

LL L, A, B, M;

// 行列
// http://www.yamamo10.jp/yamamoto/comp/cpp/ex_class/matrix.php
class Matrix {
  int row;           // 行
  int column;        // 列
  long long **p_top; // 配列の最初

public:
  Matrix(int i = 1, int j = 1) {
    if (i < 1 || j < 1)
      exit(1);
    row = i;
    column = j;
    // 配列のメモリ領域を動的に確保
    p_top = new long long *[row + 1];
    *p_top = new long long[row * column + 1];
    for (int k = 1; k <= row; k++)
      *(p_top + k) = *p_top + ((k - 1) * column);
    // 値の初期化
    for (int k1 = 1; k1 <= row; k1++)
      for (int k2 = 1; k2 <= column; k2++)
        p_top[k1][k2] = 0;
  }
  Matrix(const Matrix &cp) {
    row = cp.row;
    column = cp.column;
    // 配列のメモリ領域を動的に確保
    p_top = new long long *[row + 1];
    *p_top = new long long[row * column + 1];
    for (int k = 1; k <= row; k++)
      *(p_top + k) = *p_top + ((k - 1) * column);
    // 値のコピー
    for (int k1 = 1; k1 <= row; k1++)
      for (int k2 = 1; k2 <= column; k2++)
        p_top[k1][k2] = cp.p_top[k1][k2];
  }
  ~Matrix() {
    delete[] * p_top;
    delete[] p_top;
  }

  int row_size() { return (row); }
  int column_size() { return (column); }

  void change_size(int i, int j) {
    delete[] * p_top;
    delete[] p_top;

    if (i < 1 || j < 1)
      exit(1);
    row = i;
    column = j;
    // 配列のメモリ領域を動的に確保
    p_top = new long long *[row + 1];
    *p_top = new long long[row * column + 1];
    for (int k = 1; k <= row; k++)
      *(p_top + k) = *p_top + ((k - 1) * column);
    // 値の初期化
    for (int k1 = 1; k1 <= row; k1++)
      for (int k2 = 1; k2 <= column; k2++)
        p_top[k1][k2] = 0;
  }

  // 演算子
  long long *&operator[](int i) { return (p_top[i]); }
  Matrix operator=(const Matrix &a) {
    if (row != a.row || column != a.column) {
      change_size(a.row, a.column);
    }

    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= column; j++) {
        p_top[i][j] = a.p_top[i][j];
      }
    }
    return (*this);
  }
  Matrix operator+(const Matrix &a) {
    if (row != a.row || column != a.column)
      exit(0);
    Matrix r(row, column);
    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= column; j++) {
        r.p_top[i][j] = p_top[i][j] + a.p_top[i][j];
      }
    }
    return (r);
  }
  Matrix operator-(const Matrix &a) {
    if (row != a.row || column != a.column)
      exit(0);
    Matrix r(row, column);
    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= column; j++) {
        r.p_top[i][j] = p_top[i][j] - a.p_top[i][j];
      }
    }
    return (r);
  }
  Matrix operator*(const Matrix &a) {
    if (column != a.row)
      exit(0);
    Matrix r(row, a.column);
    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= a.column; j++) {
        for (int k = 1; k <= column; k++) {
          r.p_top[i][j] += (p_top[i][k] % M) * (a.p_top[k][j] % M);
          r.p_top[i][j] %= M;
        }
      }
    }
    return (r);
  }

  // 定数倍
  friend Matrix operator*(const Matrix &a, long long b) {
    Matrix r(a.row, a.column);
    for (int i = 1; i <= a.row; i++) {
      for (int j = 1; j <= a.column; j++) {
        r[i][j] = b * a.p_top[i][j];
      }
    }
    return (r);
  }
  friend Matrix operator*(long long b, const Matrix &a) {
    Matrix r(a.row, a.column);
    for (int i = 1; i <= a.row; i++) {
      for (int j = 1; j <= a.column; j++) {
        r[i][j] = b * a.p_top[i][j];
      }
    }
    return (r);
  }
};

// 累乗 O(log N)
long long power(long long x, long long N) {
  if (N == 1)
    return x;
  long long tmp = power(x, N / 2);
  if (N % 2 == 0)
    return tmp * tmp;
  else
    return tmp * tmp * x;
}

Matrix power(Matrix m, int N) {
  if (N == 1)
    return m;
  Matrix tmp = power(m, N / 2);
  if (N % 2 == 0)
    return tmp * tmp;
  else
    return tmp * tmp * m;
}

LL binary_search(LL maximum) {
  LL ok = -1;
  LL ng = L;
  while (ng - ok > 1) {
    LL m = (ok + ng) / 2;
    LL tmp = A + B * m;
    if (tmp <= maximum)
      ok = m;
    else
      ng = m;
  }
  return ok;
}

int main() {
  cin >> L >> A >> B >> M;
  Matrix m(1, 3);
  m[1][1] = 0;
  m[1][2] = A;
  m[1][3] = 1;
  LL now = 0;
  for (LL i = 1; i <= 18; i++) {
    Matrix mask(3, 3);
    mask[1][1] = power(10, i);
    mask[2][1] = 1;
    mask[2][2] = 1;
    mask[3][2] = B;
    mask[3][3] = 1;
    LL num = binary_search(now * 10 + 9) - binary_search(now);
    now = now * 10 + 9;
    if (num > 0)
      m = m * power(mask, num);
  }
  cout << m[1][1] << endl;
}

Fixed submission:
#include "bits/stdc++.h"
using namespace std;
#define LL long long
#define PB push_back
#define MP make_pair

LL L, A, B, M;

// 行列
// http://www.yamamo10.jp/yamamoto/comp/cpp/ex_class/matrix.php
class Matrix {
  int row;           // 行
  int column;        // 列
  long long **p_top; // 配列の最初

public:
  Matrix(int i = 1, int j = 1) {
    if (i < 1 || j < 1)
      exit(1);
    row = i;
    column = j;
    // 配列のメモリ領域を動的に確保
    p_top = new long long *[row + 1];
    *p_top = new long long[row * column + 1];
    for (int k = 1; k <= row; k++)
      *(p_top + k) = *p_top + ((k - 1) * column);
    // 値の初期化
    for (int k1 = 1; k1 <= row; k1++)
      for (int k2 = 1; k2 <= column; k2++)
        p_top[k1][k2] = 0;
  }
  Matrix(const Matrix &cp) {
    row = cp.row;
    column = cp.column;
    // 配列のメモリ領域を動的に確保
    p_top = new long long *[row + 1];
    *p_top = new long long[row * column + 1];
    for (int k = 1; k <= row; k++)
      *(p_top + k) = *p_top + ((k - 1) * column);
    // 値のコピー
    for (int k1 = 1; k1 <= row; k1++)
      for (int k2 = 1; k2 <= column; k2++)
        p_top[k1][k2] = cp.p_top[k1][k2];
  }
  ~Matrix() {
    delete[] * p_top;
    delete[] p_top;
  }

  int row_size() { return (row); }
  int column_size() { return (column); }

  void change_size(int i, int j) {
    delete[] * p_top;
    delete[] p_top;

    if (i < 1 || j < 1)
      exit(1);
    row = i;
    column = j;
    // 配列のメモリ領域を動的に確保
    p_top = new long long *[row + 1];
    *p_top = new long long[row * column + 1];
    for (int k = 1; k <= row; k++)
      *(p_top + k) = *p_top + ((k - 1) * column);
    // 値の初期化
    for (int k1 = 1; k1 <= row; k1++)
      for (int k2 = 1; k2 <= column; k2++)
        p_top[k1][k2] = 0;
  }

  // 演算子
  long long *&operator[](int i) { return (p_top[i]); }
  Matrix operator=(const Matrix &a) {
    if (row != a.row || column != a.column) {
      change_size(a.row, a.column);
    }

    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= column; j++) {
        p_top[i][j] = a.p_top[i][j];
      }
    }
    return (*this);
  }
  Matrix operator+(const Matrix &a) {
    if (row != a.row || column != a.column)
      exit(0);
    Matrix r(row, column);
    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= column; j++) {
        r.p_top[i][j] = p_top[i][j] + a.p_top[i][j];
      }
    }
    return (r);
  }
  Matrix operator-(const Matrix &a) {
    if (row != a.row || column != a.column)
      exit(0);
    Matrix r(row, column);
    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= column; j++) {
        r.p_top[i][j] = p_top[i][j] - a.p_top[i][j];
      }
    }
    return (r);
  }
  Matrix operator*(const Matrix &a) {
    if (column != a.row)
      exit(0);
    Matrix r(row, a.column);
    for (int i = 1; i <= row; i++) {
      for (int j = 1; j <= a.column; j++) {
        for (int k = 1; k <= column; k++) {
          r.p_top[i][j] += (p_top[i][k] % M) * (a.p_top[k][j] % M);
          r.p_top[i][j] %= M;
        }
      }
    }
    return (r);
  }

  // 定数倍
  friend Matrix operator*(const Matrix &a, long long b) {
    Matrix r(a.row, a.column);
    for (int i = 1; i <= a.row; i++) {
      for (int j = 1; j <= a.column; j++) {
        r[i][j] = b * a.p_top[i][j];
      }
    }
    return (r);
  }
  friend Matrix operator*(long long b, const Matrix &a) {
    Matrix r(a.row, a.column);
    for (int i = 1; i <= a.row; i++) {
      for (int j = 1; j <= a.column; j++) {
        r[i][j] = b * a.p_top[i][j];
      }
    }
    return (r);
  }
};

// 累乗 O(log N)
long long power(long long x, long long N) {
  if (N == 1)
    return x;
  long long tmp = power(x, N / 2);
  if (N % 2 == 0)
    return tmp * tmp;
  else
    return tmp * tmp * x;
}

Matrix power(Matrix m, long long N) {
  if (N == 1)
    return m;
  Matrix tmp = power(m, N / 2);
  if (N % 2 == 0)
    return tmp * tmp;
  else
    return tmp * tmp * m;
}

LL binary_search(LL maximum) {
  LL ok = -1;
  LL ng = L;
  while (ng - ok > 1) {
    LL m = (ok + ng) / 2;
    LL tmp = A + B * m;
    if (tmp <= maximum)
      ok = m;
    else
      ng = m;
  }
  return ok;
}

int main() {
  cin >> L >> A >> B >> M;
  Matrix m(1, 3);
  m[1][1] = 0;
  m[1][2] = A;
  m[1][3] = 1;
  LL now = 0;
  for (LL i = 1; i <= 18; i++) {
    Matrix mask(3, 3);
    mask[1][1] = power(10, i);
    mask[2][1] = 1;
    mask[2][2] = 1;
    mask[3][2] = B;
    mask[3][3] = 1;
    LL num = binary_search(now * 10 + 9) - binary_search(now);
    now = now * 10 + 9;
    if (num > 0)
      m = m * power(mask, num);
  }
  cout << m[1][1] << endl;
}