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

#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using ld = long double;
using VI = vector<ll>;
using VD = vector<ld>;
using VVI = vector<VI>;
using VC = vector<char>;
using VVC = vector<VC>;
using VS = vector<string>;
using PLL = pair<ll, ll>;
using PLD = pair<ld, ld>;
using VPLL = vector<PLL>;
#define REP(i, n) for (ll i = 0; i < (ll)(n); i++)
#define REPD(i, n) for (ll i = (ll)(n)-1; i >= 0; i--)
#define FOR(i, a, b) for (ll i = (a); i <= (b); i++)
#define FORD(i, a, b) for (ll i = (a); i >= (b); i--)
#define ALL(x) (x).begin(), (x).end()
#define ALLR(x) (x).rbegin(), (x).rend()
#define SIZE(x) ((ll)(x).size())
#define MAX(x) *max_element((x).begin(), (x).end())
#define MIN(x) *min_element((x).begin(), (x).end())
#define SORTR(x) sort((x).rbegin(), (x).rend())
#define SORT(x) sort((x).begin(), (x).end())
#define SUM(x) accumulate((x).begin(), (x).end(), 0)
#define FILL(x, a) fill(x.begin(), x.end(), a)
#define EACH(i, x)                                                             \\
  for (typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)

const int INF = 1 << 30;
const ld EPS = 1e-10;
const int MOD = int(1e9) + 7;
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
template <class BidirectionalIterator>
bool next_partial_permutation(BidirectionalIterator first,
                              BidirectionalIterator middle,
                              BidirectionalIterator last) {
  reverse(middle, last);
  return next_permutation(first, last);
}
#define COUT(x) cout << x << "\\n"

void Main() {
  ll result = 0;
  string S;
  cin >> S;
  VI ten(SIZE(S), 1);
  const int DIV = 2019;
  FOR(i, 1, SIZE(S)) {
    /*2019は2でも5でも割り切れないので、
     * mod2019では10に逆元が存在します。
     * そのため、10nが2019の倍数であることと
     * nが2019の倍数であることは同値です。
     * (2020ではこの性質が成り立たないので、
     * この問題では2019が使われています*/
    ten[i] = 10 * ten[i - 1]; // 10の倍数？？
    ten[i] %= DIV;            // 2019で割ったあまり
  }
  ll tmp = 0;
  ll appear[3000]; // あまりの数？？
  appear[0] = 1;
  FORD(i, SIZE(S) - 1, 0) {
    // k+ 1文字目以降の数字列を整数とみなした時の値an+ 10an−1+...+
    // 10n−k−1ak+1をTkとします
    tmp += ten[SIZE(S) - i - 1] * (S[i] - '0'); //
    // すると、(i,
    // j)が条件をみたすのは10n−j(Ti−1−Tj)が2019の倍数のとき、すなわちTi−1==Tj(mod2019)のときです
    tmp %= DIV; //
    // modの値が同じごとに個数を計算して足せば良いことになります。Ti=
    // 10Ti+1+aiより、
    result += appear[tmp]; // 2019で割り切れる数だけ加える？
    // これはDPで計算でき、modごとにm(m−1)/2
    // (mはTimod2019がある値になるiの個数)を足せば良いです。
    appear[tmp]++; //
  }
  cout << result << "\\n";
  return;
}

int main() {
  std::cin.tie(0);
  std::ios_base::sync_with_stdio(false);
  std::cout << std::fixed << std::setprecision(15);
  Main();
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using ld = long double;
using VI = vector<ll>;
using VD = vector<ld>;
using VVI = vector<VI>;
using VC = vector<char>;
using VVC = vector<VC>;
using VS = vector<string>;
using PLL = pair<ll, ll>;
using PLD = pair<ld, ld>;
using VPLL = vector<PLL>;
#define REP(i, n) for (ll i = 0; i < (ll)(n); i++)
#define REPD(i, n) for (ll i = (ll)(n)-1; i >= 0; i--)
#define FOR(i, a, b) for (ll i = (a); i <= (b); i++)
#define FORD(i, a, b) for (ll i = (a); i >= (b); i--)
#define ALL(x) (x).begin(), (x).end()
#define ALLR(x) (x).rbegin(), (x).rend()
#define SIZE(x) ((ll)(x).size())
#define MAX(x) *max_element((x).begin(), (x).end())
#define MIN(x) *min_element((x).begin(), (x).end())
#define SORTR(x) sort((x).rbegin(), (x).rend())
#define SORT(x) sort((x).begin(), (x).end())
#define SUM(x) accumulate((x).begin(), (x).end(), 0)
#define FILL(x, a) fill(x.begin(), x.end(), a)
#define EACH(i, x)                                                             \\
  for (typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)

const int INF = 1 << 30;
const ld EPS = 1e-10;
const int MOD = int(1e9) + 7;
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
template <class BidirectionalIterator>
bool next_partial_permutation(BidirectionalIterator first,
                              BidirectionalIterator middle,
                              BidirectionalIterator last) {
  reverse(middle, last);
  return next_permutation(first, last);
}
#define COUT(x) cout << x << "\\n"

bool is_prime(long long N) {
  if (N == 1)
    return false;
  for (long long i = 2; i * i <= N; ++i) {
    if (N % i == 0)
      return false;
  }
  return true;
}

void Main() {
  ll result = 0;
  string S;
  cin >> S;
  // COUT(S.size());
  for (ll j = 3; j < SIZE(S); j++) {
    for (ll i = 0; i < j; i++) {
      if (j - i + 1 < 4)
        continue;
      string T = S.substr(i, j - i + 1);
      ll num = atoll(T.c_str());
      if (num % 2019 == 0 && num != 0) {
        // COUT(i<<j);
        result++;
      }
    }
  }
  cout << result << "\\n";
  return;
}

int main() {
  std::cin.tie(0);
  std::ios_base::sync_with_stdio(false);
  std::cout << std::fixed << std::setprecision(15);
  Main();
}