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

#include <algorithm>
#include <assert.h>
#include <cmath>
#include <deque>
#include <float.h>
#include <functional>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#define LL long long
#define pii pair<int, int>
#define pLL pair<LL, LL>
#define mp make_pair
#define mt make_tuple
#define pq priority_queue<LL>
#define pqg priority_queue<int, vector<int>, greater<int>>
#define pb push_back
#define vec vector<int>
#define vecLL vector<LL>
#define vecpii vector<pii>
#define vecpLL vector<pLL>
#define vecbL vector<bool>
#define endl "\\n"
#define REP(e, v) for (auto e : v)
#define rep(i, a, n) for (LL i = a; i < n; i++)

#define INF LLONG_MAX / 2
#define DINF DBL_MAX / 2
using namespace std;

/*↓マイライブラリ↓*/

LL linp() {
  LL x;
  scanf("%lld", &x);
  return x;
}

LL mod(LL i) { return i % 1000000007; }

LL gcd(LL i, LL j) {
  if (j != 0)
    return gcd(j, i % j);
  else
    return i;
}

pLL extgcd(LL a, LL b, LL c) { // ax+by = cの解

  pLL ans;

  if (c % gcd(a, b) != 0) {
    return pLL(-1, -1);
  } else {

    if (b != 0) {
      pLL next = extgcd(b, a % b, c);
      ans.first = next.second;
      ans.second = next.first - (a / b) * next.second;
    } else {
      ans = pLL(c / a, 0);
    }
  }

  return ans;
}

vecLL Eratosthenes(LL n) { // 素数のベクトルを返す

  bool isPrime[n];
  fill(isPrime, isPrime + n, true);

  isPrime[0] = isPrime[1] = false;
  rep(i, 2, sqrt(n) + 1) {
    if (isPrime[i]) {
      for (LL j = 2 * i; j <= n; j += i) {
        isPrime[j] = false;
      }
    }
  }

  vecLL P;

  rep(i, 2, n + 1) {
    if (isPrime[i]) {
      P.push_back(i);
    }
  }

  return P;
}
class Graph {

public:
  struct edge { // 枝
    LL to, cost;
    double dcost; // コストが整数でない場合に使う
  };

  struct vertex { // 頂点(枝付き)
    LL key;
    double dkey;        // キーが整数でない場合に使う
    vector<edge> edges; // 頂点から伸びる枝
  };

  LL V;             // 頂点数
  vertex *vertices; // グラフ

  Graph(LL v) {               // 頂点数を指定してグラフの初期化
    V = v;                    // 頂点数
    vertices = new vertex[V]; // 頂点集合

    rep(i, 0, V) {
      vertices[i].key = i;  // キー初期値はインデックスそのもの
      vertices[i].dkey = i; // キー初期値はインデックスそのもの
    }
  }

  void setDE(LL i, LL j, LL cos) { // i→jにコストcosの有向枝を加える

    edge e;
    e.to = j;
    e.cost = cos;

    vertices[i].edges.push_back(e);

    return;
  }

  void setDE(LL i, LL j, double dcos) { // i→jにコストcosの有向枝を加える

    edge e;
    e.to = j;
    e.dcost = dcos;

    vertices[i].edges.push_back(e);

    return;
  }

  void setUDE(LL i, LL j, LL cos) { //(i,j)にコストcosの無向枝を加える

    edge ei, ej;
    ei.to = j;
    ej.to = i;
    ei.cost = ej.cost = cos;

    vertices[i].edges.push_back(ei);
    vertices[j].edges.push_back(ej);

    return;
  }

  void setUDE(LL i, LL j, double dcos) { //(i,j)にコストcosの無向枝を加える

    edge ei, ej;
    ei.to = j;
    ej.to = i;
    ei.dcost = ej.dcost = dcos;

    vertices[i].edges.push_back(ei);
    vertices[j].edges.push_back(ej);

    return;
  }

  void setKey(LL i, LL newKey) { // キー変更
    vertices[i].key = newKey;
  }

  void setKey(LL i, double newKey) { // キー変更
    vertices[i].key = newKey;
  }

  edge getEdge(LL i, LL j) {

    rep(a, 0, vertices[i].edges.size()) {
      if (vertices[i].edges[a].to == j) {
        return vertices[i].edges[a];
      }
    }

    return (edge){j, INF, DINF}; // なければ,コストINFの枝を返す
  }

  void bellman_ford(LL s, LL b[]) {
    fill(b, b + V, INF);

    b[s] = 0;

    while (true) {

      bool update = false;
      rep(i, 0, V) {
        rep(j, 0, vertices[i].edges.size()) {
          edge e = vertices[i].edges[j];

          if (b[e.to] > b[i] + e.cost) {
            b[e.to] = b[i] + e.cost;
            update = true;
          }
        }
      }
      if (!update)
        break;
    }

    return;
  }

  void
  dijkstra(LL s,
           LL d[]) { // ダイクストラ(始点を入力とし、各点への最小距離を返す)

    priority_queue<pLL, vector<pLL>, greater<pLL>> que;

    fill(d, d + V, INF);
    d[s] = 0;
    que.push(pLL(0, s));

    while (!que.empty()) {
      pLL p = que.top();
      que.pop();
      LL v = p.second;
      if (d[v] < p.first)
        continue;

      rep(i, 0, vertices[v].edges.size()) {
        edge e = vertices[v].edges[i];
        if (d[e.to] > d[v] + e.cost) {
          d[e.to] = d[v] + e.cost;
          que.push(pLL(d[e.to], e.to));
        }
      }
    }

    return;
  }

  void warshall_floyd(LL **w) {

    rep(i, 0, V) {
      rep(j, 0, V) { w[i][j] = INF; }
    }
    rep(i, 0, V) {
      rep(j, 0, vertices[i].edges.size()) {
        w[i][vertices[i].edges[j].to] = vertices[i].edges[j].cost;
      }
    }

    rep(i, 0, V) { w[i][i] = 0; }

    rep(i, 0, V) {
      rep(j, 0, V) {
        rep(k, 0, V) { w[i][j] = min(w[i][j], w[i][k] + w[k][j]); }
      }
    }
  }
};

class UF {
public:
  LL N;
  LL *par;
  LL *rank;

  UF(LL n) {
    N = n;

    par = new LL[N];
    rank = new LL[N];

    rep(i, 0, N) {
      par[i] = i;
      rank[i] = i;
    }

    return;
  }

  LL root(LL x) {
    if (x == par[x])
      return x;
    else
      return par[x] = root(par[x]);
  }

  bool same(LL x, LL y) { return (root(x) == root(y)); }

  void Union(LL x, LL y) {
    LL rtx = root(x);
    LL rty = root(y);

    if (rank[rtx] < rank[rty]) {
      par[rtx] = rty;
    } else {
      par[rty] = rtx;
      if (rank[rtx] == rank[rty]) {
        rank[rtx]++;
      }
    }
  }
};

class ST {};

/*↑マイライブラリ↑*/

LL A() { return 0; }

LL B() { return 0; }

LL C() {
  LL N = linp();

  string s[N];

  set<string> sset;
  rep(i, 0, N) {
    cin >> s[i];
    sset.insert(s[i]);
  }

  cout << sset.size() << endl;
  return 0;
}

LL D() {

  string s;

  cin >> s;

  LL N = s.length();

  LL T[N + 1]; // T[i-1]はi文字目以降の文字列を整数としてみたとき

  T[N] = 0;
  LL Tnum[2019] = {0};
  Tnum[T[N]]++;

  LL fac = 1;

  for (LL i = N - 1; i >= 0; i--) {
    T[i] = ((T[i + 1] % 2019) + fac * (s[i] - '0')) % 2019;
    Tnum[T[i]]++;
    fac = (fac * 10) % 2019;
  }

  LL ans = 0;

  rep(i, 0, 2019) { ans += (Tnum[i] * (Tnum[i] - 1)) / 2; }
  //	rep(i,0,N){
  //		rep(j,i+1,N+1){
  //			if(T[i]%2019 == T[j]%2019){
  //			//	cout << T[i] - T[j] << "("<< i << "," << j << ")" <<
  //endl; 				count++;
  //			}
  //		}
  //	}

  cout << ans << endl;

  return 0;
}

LL E() { return 0; }

signed main() {
  // A();
  // B();
  // C();
  D();
  // E();
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <assert.h>
#include <cmath>
#include <deque>
#include <float.h>
#include <functional>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#define LL long long
#define pii pair<int, int>
#define pLL pair<LL, LL>
#define mp make_pair
#define mt make_tuple
#define pq priority_queue<LL>
#define pqg priority_queue<int, vector<int>, greater<int>>
#define pb push_back
#define vec vector<int>
#define vecLL vector<LL>
#define vecpii vector<pii>
#define vecpLL vector<pLL>
#define vecbL vector<bool>
#define endl "\\n"
#define REP(e, v) for (auto e : v)
#define rep(i, a, n) for (LL i = a; i < n; i++)

#define INF LLONG_MAX / 2
#define DINF DBL_MAX / 2
using namespace std;

/*↓マイライブラリ↓*/

LL linp() {
  LL x;
  scanf("%lld", &x);
  return x;
}

LL mypow(LL n, LL x, LL mod) {
  LL a = 1;
  rep(i, 0, x) { a = (a * n) % mod; }

  return a;
}

LL mod(LL i) { return i % 1000000007; }

LL gcd(LL i, LL j) {
  if (j != 0)
    return gcd(j, i % j);
  else
    return i;
}

pLL extgcd(LL a, LL b, LL c) { // ax+by = cの解

  pLL ans;

  if (c % gcd(a, b) != 0) {
    return pLL(-1, -1);
  } else {

    if (b != 0) {
      pLL next = extgcd(b, a % b, c);
      ans.first = next.second;
      ans.second = next.first - (a / b) * next.second;
    } else {
      ans = pLL(c / a, 0);
    }
  }

  return ans;
}

vecLL Eratosthenes(LL n) { // 素数のベクトルを返す

  bool isPrime[n];
  fill(isPrime, isPrime + n, true);

  isPrime[0] = isPrime[1] = false;
  rep(i, 2, sqrt(n) + 1) {
    if (isPrime[i]) {
      for (LL j = 2 * i; j <= n; j += i) {
        isPrime[j] = false;
      }
    }
  }

  vecLL P;

  rep(i, 2, n + 1) {
    if (isPrime[i]) {
      P.push_back(i);
    }
  }

  return P;
}
class Graph {

public:
  struct edge { // 枝
    LL to, cost;
    double dcost; // コストが整数でない場合に使う
  };

  struct vertex { // 頂点(枝付き)
    LL key;
    double dkey;        // キーが整数でない場合に使う
    vector<edge> edges; // 頂点から伸びる枝
  };

  LL V;             // 頂点数
  vertex *vertices; // グラフ

  Graph(LL v) {               // 頂点数を指定してグラフの初期化
    V = v;                    // 頂点数
    vertices = new vertex[V]; // 頂点集合

    rep(i, 0, V) {
      vertices[i].key = i;  // キー初期値はインデックスそのもの
      vertices[i].dkey = i; // キー初期値はインデックスそのもの
    }
  }

  void setDE(LL i, LL j, LL cos) { // i→jにコストcosの有向枝を加える

    edge e;
    e.to = j;
    e.cost = cos;

    vertices[i].edges.push_back(e);

    return;
  }

  void setDE(LL i, LL j, double dcos) { // i→jにコストcosの有向枝を加える

    edge e;
    e.to = j;
    e.dcost = dcos;

    vertices[i].edges.push_back(e);

    return;
  }

  void setUDE(LL i, LL j, LL cos) { //(i,j)にコストcosの無向枝を加える

    edge ei, ej;
    ei.to = j;
    ej.to = i;
    ei.cost = ej.cost = cos;

    vertices[i].edges.push_back(ei);
    vertices[j].edges.push_back(ej);

    return;
  }

  void setUDE(LL i, LL j, double dcos) { //(i,j)にコストcosの無向枝を加える

    edge ei, ej;
    ei.to = j;
    ej.to = i;
    ei.dcost = ej.dcost = dcos;

    vertices[i].edges.push_back(ei);
    vertices[j].edges.push_back(ej);

    return;
  }

  void setKey(LL i, LL newKey) { // キー変更
    vertices[i].key = newKey;
  }

  void setKey(LL i, double newKey) { // キー変更
    vertices[i].key = newKey;
  }

  edge getEdge(LL i, LL j) {

    rep(a, 0, vertices[i].edges.size()) {
      if (vertices[i].edges[a].to == j) {
        return vertices[i].edges[a];
      }
    }

    return (edge){j, INF, DINF}; // なければ,コストINFの枝を返す
  }

  void bellman_ford(LL s, LL b[]) {
    fill(b, b + V, INF);

    b[s] = 0;

    while (true) {

      bool update = false;
      rep(i, 0, V) {
        rep(j, 0, vertices[i].edges.size()) {
          edge e = vertices[i].edges[j];

          if (b[e.to] > b[i] + e.cost) {
            b[e.to] = b[i] + e.cost;
            update = true;
          }
        }
      }
      if (!update)
        break;
    }

    return;
  }

  void
  dijkstra(LL s,
           LL d[]) { // ダイクストラ(始点を入力とし、各点への最小距離を返す)

    priority_queue<pLL, vector<pLL>, greater<pLL>> que;

    fill(d, d + V, INF);
    d[s] = 0;
    que.push(pLL(0, s));

    while (!que.empty()) {
      pLL p = que.top();
      que.pop();
      LL v = p.second;
      if (d[v] < p.first)
        continue;

      rep(i, 0, vertices[v].edges.size()) {
        edge e = vertices[v].edges[i];
        if (d[e.to] > d[v] + e.cost) {
          d[e.to] = d[v] + e.cost;
          que.push(pLL(d[e.to], e.to));
        }
      }
    }

    return;
  }

  void warshall_floyd(LL **w) {

    rep(i, 0, V) {
      rep(j, 0, V) { w[i][j] = INF; }
    }
    rep(i, 0, V) {
      rep(j, 0, vertices[i].edges.size()) {
        w[i][vertices[i].edges[j].to] = vertices[i].edges[j].cost;
      }
    }

    rep(i, 0, V) { w[i][i] = 0; }

    rep(i, 0, V) {
      rep(j, 0, V) {
        rep(k, 0, V) { w[i][j] = min(w[i][j], w[i][k] + w[k][j]); }
      }
    }
  }
};

class UF {
public:
  LL N;
  LL *par;
  LL *rank;

  UF(LL n) {
    N = n;

    par = new LL[N];
    rank = new LL[N];

    rep(i, 0, N) {
      par[i] = i;
      rank[i] = i;
    }

    return;
  }

  LL root(LL x) {
    if (x == par[x])
      return x;
    else
      return par[x] = root(par[x]);
  }

  bool same(LL x, LL y) { return (root(x) == root(y)); }

  void Union(LL x, LL y) {
    LL rtx = root(x);
    LL rty = root(y);

    if (rank[rtx] < rank[rty]) {
      par[rtx] = rty;
    } else {
      par[rty] = rtx;
      if (rank[rtx] == rank[rty]) {
        rank[rtx]++;
      }
    }
  }
};

class ST {};

/*↑マイライブラリ↑*/

LL A() { return 0; }

LL B() { return 0; }

LL C() {
  LL N = linp();

  string s[N];

  set<string> sset;
  rep(i, 0, N) {
    cin >> s[i];
    sset.insert(s[i]);
  }

  cout << sset.size() << endl;
  return 0;
}

LL D() {

  string s;

  cin >> s;

  LL N = s.length();

  LL T[N + 1]; // T[i-1]はi文字目以降の文字列を整数としてみたとき

  T[N] = 0;
  LL Tnum[2019] = {0};
  Tnum[T[N]]++;

  for (LL i = N - 1; i >= 0; i--) {
    T[i] =
        ((T[i + 1] % 2019) + mypow(10, N - 1 - i, 2019) * (s[i] - '0')) % 2019;
    Tnum[T[i]]++;
  }

  LL ans = 0;

  rep(i, 0, 2019) { ans += (Tnum[i] * (Tnum[i] - 1)) / 2; }
  //	rep(i,0,N){
  //		rep(j,i+1,N+1){
  //			if(T[i]%2019 == T[j]%2019){
  //			//	cout << T[i] - T[j] << "("<< i << "," << j << ")" <<
  //endl; 				count++;
  //			}
  //		}
  //	}

  cout << ans << endl;

  return 0;
}

LL E() { return 0; }

signed main() {
  // A();
  // B();
  // C();
  D();
  // E();
  return 0;
}