Problem p03016 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cctype>
#include <climits>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
using namespace std;
using ll = long long;
template <typename T>
using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;
const ll inf = 1LL << 60;
#define all(x) (x).begin(), (x).end()
#define puts(x) cout << x << endl
#define rep(i, m, n) for (ll i = m; i < n; ++i)
#define pb push_back
#define fore(i, a) for (auto &i : a)
#define rrep(i, m, n) for (ll i = m; i >= n; --i)

ll L, A, B, M;
vector<vector<ll>> matrix_mul(vector<vector<ll>> a, vector<vector<ll>> b) {
  vector<vector<ll>> res(a.size(), vector<ll>(b[0].size()));
  for (int i = 0; i < a.size(); i++) {
    for (int j = 0; j < b[0].size(); j++) {
      ll temp = 0;
      for (int k = 0; k < b.size(); k++) {
        a[i][k] %= M;
        b[k][j] %= M;
        temp += (a[i][k] * b[k][j]) % M;
        temp %= M;
      }
      res[i][j] = temp;
    }
  }
  return res;
}
vector<vector<ll>> matrix_pow(vector<vector<ll>> a, ll n) {
  vector<vector<ll>> E(a.size(), vector<ll>(a.size(), 0));
  for (int i = 0; i < a.size(); i++) {
    for (int j = 0; j < a.size(); j++) {
      E[i][j] = (i == j);
    }
  }
  if (n == 0)
    return E;
  else if (n % 2 == 0)
    return matrix_mul(matrix_pow(a, n / 2), matrix_pow(a, n / 2));
  else
    return matrix_mul(a, matrix_pow(a, n - 1));
}
ll po(ll n) {
  ll ret = 1;
  for (int i = 0; i < n; i++)
    ret *= 10LL;
  return ret;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  cin >> L >> A >> B >> M;
  ll pre = -1;
  vector<vector<ll>> cur(3, vector<ll>(1, 0));
  cur[1][0] = A;
  cur[2][0] = 1;
  for (int i = 1; i <= 18; i++) {
    vector<vector<ll>> M(3, vector<ll>(3, 0));
    M[0] = {po(i), 1, 0};
    M[1] = {0, 1, B};
    M[2] = {0, 0, 1};
    if (A + (L - 1) * B < po(i)) {
      cur = matrix_mul(matrix_pow(M, L - 1 - pre), cur);
      break;
    }
    ll ok = pre, ng = L - 1;
    while (ng - ok > 1) {
      ll mid = (ng + ok) / 2LL;
      if (A + mid * B < po(i))
        ok = mid;
      else
        ng = mid;
    }
    vector<vector<ll>> temp = matrix_pow(M, ok - pre);
    cur = matrix_mul(temp, cur);
    pre = ok;
  }
  puts(cur[0][0]);

  return 0;
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cctype>
#include <climits>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
using namespace std;
using ll = long long;
template <typename T>
using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;
const ll inf = 1LL << 60;
#define all(x) (x).begin(), (x).end()
#define puts(x) cout << x << endl
#define rep(i, m, n) for (ll i = m; i < n; ++i)
#define pb push_back
#define fore(i, a) for (auto &i : a)
#define rrep(i, m, n) for (ll i = m; i >= n; --i)

ll L, A, B, M;
vector<vector<ll>> matrix_mul(vector<vector<ll>> a, vector<vector<ll>> b) {
  vector<vector<ll>> res(a.size(), vector<ll>(b[0].size()));
  for (int i = 0; i < a.size(); i++) {
    for (int j = 0; j < b[0].size(); j++) {
      ll temp = 0;
      for (int k = 0; k < b.size(); k++) {
        a[i][k] %= M;
        b[k][j] %= M;
        temp += (a[i][k] * b[k][j]) % M;
        temp %= M;
      }
      res[i][j] = temp;
    }
  }
  return res;
}
vector<vector<ll>> matrix_pow(vector<vector<ll>> a, ll n) {
  vector<vector<ll>> E(a.size(), vector<ll>(a.size(), 0));
  for (int i = 0; i < a.size(); i++) {
    for (int j = 0; j < a.size(); j++) {
      E[i][j] = (i == j);
    }
  }
  while (n > 0) {
    if (n & 1)
      E = matrix_mul(E, a);
    a = matrix_mul(a, a);
    n >>= 1;
  }
  return E;
}
ll po(ll n) {
  ll ret = 1;
  for (int i = 0; i < n; i++)
    ret *= 10LL;
  return ret;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  cin >> L >> A >> B >> M;
  ll pre = -1;
  vector<vector<ll>> cur(3, vector<ll>(1, 0));
  cur[1][0] = A;
  cur[2][0] = 1;
  for (int i = 1; i <= 18; i++) {
    vector<vector<ll>> M(3, vector<ll>(3, 0));
    M[0] = {po(i), 1, 0};
    M[1] = {0, 1, B};
    M[2] = {0, 0, 1};
    if (A + (L - 1) * B < po(i)) {
      cur = matrix_mul(matrix_pow(M, L - 1 - pre), cur);
      break;
    }
    ll ok = pre, ng = L - 1;
    while (ng - ok > 1) {
      ll mid = (ng + ok) / 2LL;
      if (A + mid * B < po(i))
        ok = mid;
      else
        ng = mid;
    }
    vector<vector<ll>> temp = matrix_pow(M, ok - pre);
    cur = matrix_mul(temp, cur);
    pre = ok;
  }
  puts(cur[0][0]);

  return 0;
}