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

#include <bits/stdc++.h>
#include <regex>
#ifdef _DEBUG
#include "debug.h"
#endif
#define int ll
#define float double
#define FOR(i, s, e) for (int i = int(s); i < int(e); ++i)
#define REP(i, e) FOR(i, 0, e)
#define all(v) (v).begin(), (v).end()
#define mkpr make_pair
#define mktp make_tuple
#define tv(tp, i) get<(i)>(tp)
#define CLEAR(obj) obj = decltype(obj)()
#define var auto
#define OUT(type) type &
#define IN(type) const type &
#define self (*this)
#define in :
#define True true
#define False false
using namespace std;
using int32 = int32_t;
using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vc = vector<char>;
using vvc = vector<vc>;
using vf = vector<float>;
using vvf = vector<vf>;
using vd = vector<double>;
using vvd = vector<vd>;
using str = string;
using vs = vector<string>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pff = pair<float, float>;
using pdd = pair<double, double>;
using psl = pair<string, ll>;
using tiii = tuple<int, int, int>;
using tlll = tuple<ll, ll, ll>;
static const int MGN = 10;
static const int ARYSZ_MAX = (int)1e7;
static const ll LINF = LLONG_MAX / 2;
#ifdef int
static const int INF = LINF;
#else
static const int INF = INT_MAX / 2;
#endif
static double EPS = 1e-9;
#define FASTCIN()                                                              \\
  cin.tie(0);                                                                  \\
  ios::sync_with_stdio(false);
#ifdef IMPORT_SAMPLE
#define DEBUG_IMPORT(file)                                                     \\
  vs args(argv, argv + argc);                                                  \\
  str sample = make_sample(args, file);                                        \\
  ifstream ifs(sample);                                                        \\
  cin.rdbuf(ifs.rdbuf());
#else
#define DEBUG_IMPORT(file)
#endif
static inline int ord(char c) { return (int)c; }
static inline char chr(int n) { return (char)n; }
static inline bool DBLEQ(double a, double b) { return abs(a - b) < EPS; }
static inline void EPR(str msg) { cerr << msg << endl; }
static inline void AST(bool exp, str msg) {
  if (!exp) {
    EPR(msg);
  }
  assert(exp);
}
static inline void TAST(bool exp, str msg) {
  if (!exp) {
    EPR(msg);
  }
  while (!exp) {
  }
}

struct llm {
  ll MOD;
  ll val;
  llm(ll val = 0, ll MOD = (ll)1e9 + 7) {
    self.MOD = MOD;
    self.val = (val % MOD + MOD) % MOD;
  }
  llm(string S, ll MOD = (ll)1e9 + 7) {
    self.MOD = MOD;
    self.val = 0;
    if (S.empty())
      return;
    string r = S;
    reverse(r.begin(), r.end());
    int N = r.size();
    ll d = 1;
    REP(i, N) {
      self.val += (r[i] - '0') * d;
      self.val %= MOD;
      d *= 10;
      d %= MOD;
    }
  }
  bool operator==(IN(llm) other) const {
    return self.val % MOD == other.val % MOD;
  }
  llm operator-() const { return llm(-val); }
  llm &operator+=(const llm other) {
    if ((val += other.val) >= MOD)
      val -= MOD;
    return self;
  }
  llm &operator-=(const llm other) {
    if ((val += MOD - other.val) >= MOD)
      val -= MOD;
    return self;
  }
  llm &operator*=(const llm other) {
    (val *= other.val) %= MOD;
    return self;
  }
  llm operator+(const llm other) const { return llm(*this) += other; }
  llm operator-(const llm other) const { return llm(self) -= other; }
  llm operator*(const llm other) const { return llm(self) *= other; }
  llm pow(ll n) const {
    if (n == 0)
      return 1;
    llm x = self.pow(n / 2);
    x *= x;
    if (n % 2 == 1)
      x *= self;
    return x;
  }
  llm inv() const { return pow(MOD - 2); }
  llm &operator/=(const llm other) { return self *= other.inv(); }
  llm operator/(const llm other) const { return llm(self) /= other; }
};

istream &operator>>(istream &isr, const llm &x) { return isr >> x.val; }

ostream &operator<<(ostream &osr, const llm &x) { return osr << x.val; }

int32 main(int32 argc, char *argv[]) {
  FASTCIN();
  DEBUG_IMPORT("sample-1");

  int MOD = 2019;
  str S;
  cin >> S;
  int N = S.size();

  int cnt = 0;
  map<int, int> dp;
  // dp[i] := [i,N) までの部分文字列から得られる自然数の mod 2019 の出現回数
  dp[0] = 1; // [N,N) の空文字は 0 とみなす

  llm num(0, MOD);
  llm d(1, MOD);
  reverse(all(S));

  REP(i, N) {
    num += d * (S[i] - '0');
    d *= 10;
    if (dp.count(num.val) > 0)
      cnt += dp[num.val];

    dp[num.val] += 1;
  }

  int ans = cnt;
  cout << ans << endl;

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#include <regex>
#ifdef _DEBUG
#include "debug.h"
#endif
#define int ll
#define float double
#define FOR(i, s, e) for (int i = int(s); i < int(e); ++i)
#define REP(i, e) FOR(i, 0, e)
#define all(v) (v).begin(), (v).end()
#define mkpr make_pair
#define mktp make_tuple
#define tv(tp, i) get<(i)>(tp)
#define CLEAR(obj) obj = decltype(obj)()
#define var auto
#define OUT(type) type &
#define IN(type) const type &
#define self (*this)
#define in :
#define True true
#define False false
using namespace std;
using int32 = int32_t;
using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vc = vector<char>;
using vvc = vector<vc>;
using vf = vector<float>;
using vvf = vector<vf>;
using vd = vector<double>;
using vvd = vector<vd>;
using str = string;
using vs = vector<string>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pff = pair<float, float>;
using pdd = pair<double, double>;
using psl = pair<string, ll>;
using tiii = tuple<int, int, int>;
using tlll = tuple<ll, ll, ll>;
static const int MGN = 10;
static const int ARYSZ_MAX = (int)1e7;
static const ll LINF = LLONG_MAX / 2;
#ifdef int
static const int INF = LINF;
#else
static const int INF = INT_MAX / 2;
#endif
static double EPS = 1e-9;
#define FASTCIN()                                                              \\
  cin.tie(0);                                                                  \\
  ios::sync_with_stdio(false);
#ifdef IMPORT_SAMPLE
#define DEBUG_IMPORT(file)                                                     \\
  vs args(argv, argv + argc);                                                  \\
  str sample = make_sample(args, file);                                        \\
  ifstream ifs(sample);                                                        \\
  cin.rdbuf(ifs.rdbuf());
#else
#define DEBUG_IMPORT(file)
#endif
static inline int ord(char c) { return (int)c; }
static inline char chr(int n) { return (char)n; }
static inline bool DBLEQ(double a, double b) { return abs(a - b) < EPS; }
static inline void EPR(str msg) { cerr << msg << endl; }
static inline void AST(bool exp, str msg) {
  if (!exp) {
    EPR(msg);
  }
  assert(exp);
}
static inline void TAST(bool exp, str msg) {
  if (!exp) {
    EPR(msg);
  }
  while (!exp) {
  }
}

struct llm {
  ll MOD;
  ll val;
  llm(ll val = 0, ll MOD = (ll)1e9 + 7) {
    self.MOD = MOD;
    self.val = (val % MOD + MOD) % MOD;
  }
  llm(string S, ll MOD = (ll)1e9 + 7) {
    self.MOD = MOD;
    self.val = 0;
    if (S.empty())
      return;
    string r = S;
    reverse(r.begin(), r.end());
    int N = r.size();
    ll d = 1;
    REP(i, N) {
      self.val += (r[i] - '0') * d;
      self.val %= MOD;
      d *= 10;
      d %= MOD;
    }
  }
  bool operator==(IN(llm) other) const {
    return self.val % MOD == other.val % MOD;
  }
  llm operator-() const { return llm(-val); }
  llm &operator+=(const llm other) {
    if ((val += other.val) >= MOD)
      val -= MOD;
    return self;
  }
  llm &operator-=(const llm other) {
    if ((val += MOD - other.val) >= MOD)
      val -= MOD;
    return self;
  }
  llm &operator*=(const llm other) {
    (val *= other.val) %= MOD;
    return self;
  }
  llm operator+(const llm other) const { return llm(*this) += other; }
  llm operator-(const llm other) const { return llm(self) -= other; }
  llm operator*(const llm other) const { return llm(self) *= other; }
  llm pow(ll n) const {
    if (n == 0)
      return 1;
    llm x = self.pow(n / 2);
    x *= x;
    if (n % 2 == 1)
      x *= self;
    return x;
  }
  llm inv() const { return pow(MOD - 2); }
  llm &operator/=(const llm other) { return self *= other.inv(); }
  llm operator/(const llm other) const { return llm(self) /= other; }
};

istream &operator>>(istream &isr, const llm &x) { return isr >> x.val; }

ostream &operator<<(ostream &osr, const llm &x) { return osr << x.val; }

int32 main(int32 argc, char *argv[]) {
  FASTCIN();
  DEBUG_IMPORT("sample-1");

  int MOD = 2019;
  str S;
  cin >> S;
  int N = S.size();

  int cnt = 0;
  map<int, int> dp;
  // dp[i] := [i,N) までの部分文字列から得られる自然数の mod 2019 の出現回数
  dp[0] = 1; // [N,N) の空文字は 0 とみなす
  for (int i = N - 1; i >= 0; i--) {
    llm num(S.substr(i), MOD);

    if (dp.count(num.val) > 0)
      cnt += dp[num.val];

    dp[num.val] += 1;
  }

  int ans = cnt;
  cout << ans << endl;

  return 0;
}