Problem p03322 (C++)

Buggy submission (status: Runtime Error):
/*
    _____
  .'     '.
 /  0   0  \
|     ^     |
|  \     /  |
 \  '---'  /
  '._____.'
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

struct chash {
  int operator()(int x) const {
    x ^= (x >> 20) ^ (x >> 12);
    return x ^ (x >> 7) ^ (x >> 4);
  }
};

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T, typename U> using hashtable = gp_hash_table<T, U, chash>;
random_device(rd);
mt19937 rng(rd());

template <class T> void readi(T &x) {
  T input = 0;
  bool negative = false;
  char c = ' ';
  while (c < '-') {
    c = getchar();
  }
  if (c == '-') {
    negative = true;
    c = getchar();
  }
  while (c >= '0') {
    input = input * 10 + (c - '0');
    c = getchar();
  }
  if (negative) {
    input = -input;
  }
  x = input;
}
template <class T> void printi(T output) {
  if (output == 0) {
    putchar('0');
    return;
  }
  if (output < 0) {
    putchar('-');
    output = -output;
  }
  int aout[20];
  int ilen = 0;
  while (output) {
    aout[ilen] = ((output % 10));
    output /= 10;
    ilen++;
  }
  for (int i = ilen - 1; i >= 0; i--) {
    putchar(aout[i] + '0');
  }
  return;
}
template <class T> void ckmin(T &a, T b) { a = min(a, b); }
template <class T> void ckmax(T &a, T b) { a = max(a, b); }
template <class T, class U> T nmod(T &x, U mod) {
  if (x >= mod)
    x -= mod;
}
template <class T> T randomize(T mod) {
  return (uniform_int_distribution<T>(0, mod - 1))(rng);
}

#define y0 ___y0
#define y1 ___y1
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second
#define debug(x) cerr << #x << " = " << x << endl;

const long double PI = 4.0 * atan(1.0);
const long double EPS = 1e-10;

#define MAGIC 347
#define SINF 10007
#define CO 1000007
#define INF 1000000007
#define BIG 1000000931
#define LARGE 1696969696967ll
#define GIANT 2564008813937411ll
#define LLINF 2696969696969696969ll
#define MAXN 250013

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;

int N;
int arr[MAXN];
pll S;
long long ans;
map<ll, int> need;

ll expo(ll a, ll e, ll mod) {
  if (e == 0) {
    return 1;
  }
  ll was = expo(a, e / 2, mod);
  if (e % 2) {
    return was * was % mod * a % mod;
  }
  return was * was % mod;
}
ll modinv(ll a, ll e) { return expo(a, e - 2, e); }
pll INV = {modinv(CO, INF), modinv(CO, BIG)};
void solve(int L, int R) {
  if (L == R) {
    return;
  }
  need.clear();
  int mid = (L + R) >> 1;
  // start from L...mid, end at mid + 1....R
  pair<pll, pll> trans = MP(MP(1, 0), MP(1, 0));
  pll inv = MP(1, 1);
  for (int i = mid + 1; i <= R; i++) {
    if (arr[i] == 0) {
      trans.fi.fi *= INV.fi;
      trans.fi.fi %= INF;
      trans.fi.se *= INV.fi;
      trans.fi.se %= INF;
      trans.se.fi *= INV.se;
      trans.se.fi %= BIG;
      trans.se.se *= INV.se;
      trans.se.se %= BIG;
      inv.fi *= CO;
      inv.fi %= INF;
      inv.se *= CO;
      inv.se %= BIG;
    }
    if (arr[i] == 1) {
      trans.fi.fi *= CO;
      trans.fi.fi %= INF;
      trans.fi.se *= CO;
      trans.fi.se %= INF;
      trans.se.fi *= CO;
      trans.se.fi %= BIG;
      trans.se.se *= CO;
      trans.se.se %= BIG;
      inv.fi *= INV.fi;
      inv.fi %= INF;
      inv.se *= INV.se;
      inv.se %= BIG;
    }
    if (arr[i] == 2) {
      trans.fi.se++;
      nmod(trans.fi.se, INF);
      trans.se.se++;
      nmod(trans.se.se, BIG);
    }
    if (arr[i] == 3) {
      trans.fi.se--;
      trans.fi.se += INF;
      nmod(trans.fi.se, INF);
      trans.se.se--;
      trans.se.se += BIG;
      nmod(trans.se.se, BIG);
    }
    pll dif = {(S.fi - trans.fi.se) * inv.fi, (S.se - trans.se.se) * inv.se};
    dif.fi %= INF;
    dif.fi += INF;
    nmod(dif.fi, INF);
    dif.se %= BIG;
    dif.se += BIG;
    nmod(dif.se, BIG);
    need[dif.fi * BIG + dif.se]++;
  }
  trans = MP(MP(1, 0), MP(1, 0));
  for (int i = mid; i >= L; i--) {
    if (arr[i] == 0) {
      trans.fi.fi *= INV.fi;
      trans.fi.fi %= INF;
      trans.se.fi *= INV.se;
      trans.se.fi %= BIG;
    }
    if (arr[i] == 1) {
      trans.fi.fi *= CO;
      trans.fi.fi %= INF;
      trans.se.fi *= CO;
      trans.se.fi %= BIG;
    }
    if (arr[i] == 2) {
      trans.fi.se += trans.fi.fi;
      nmod(trans.fi.se, INF);
      trans.se.se += trans.se.fi;
      nmod(trans.se.se, BIG);
    }
    if (arr[i] == 3) {
      trans.fi.se -= trans.fi.fi;
      trans.fi.se += INF;
      nmod(trans.fi.se, INF);
      trans.se.se -= trans.se.fi;
      trans.se.se += BIG;
      nmod(trans.se.se, BIG);
    }
    ans += need[trans.fi.se * BIG + trans.se.se];
  }
  solve(L, mid);
  solve(mid + 1, R);
}

int32_t main() {
  ios_base::sync_with_stdio(0);
  // cout << fixed << setprecision(10);
  // cerr << fixed << setprecision(10);
  freopen("file.in", "r", stdin);
  freopen("file.out", "w", stdout);
  cin >> N;
  string temps;
  cin >> temps;
  for (int i = 0; i < N; i++) {
    if (temps[i] == '<') {
      arr[i] = 0;
    }
    if (temps[i] == '>') {
      arr[i] = 1;
    }
    if (temps[i] == '+') {
      arr[i] = 2;
    }
    if (temps[i] == '-') {
      arr[i] = 3;
    }
  }
  reverse(arr, arr + N);
  for (int i = 0; i < N; i++) {
    if (arr[i] == 0) {
      S.fi *= INV.fi;
      S.fi %= INF;
      S.se *= INV.se;
      S.se %= BIG;
    }
    if (arr[i] == 1) {
      S.fi *= CO;
      S.fi %= INF;
      S.se *= CO;
      S.se %= BIG;
    }
    if (arr[i] == 2) {
      S.fi++;
      nmod(S.fi, INF);
      S.se++;
      nmod(S.se, BIG);
    }
    if (arr[i] == 3) {
      S.fi--;
      S.fi += INF;
      nmod(S.fi, INF);
      S.se--;
      S.se += BIG;
      nmod(S.se, BIG);
    }
  }
  for (int i = 0; i < N; i++) {
    if (arr[i] == 0) {
      if (S == MP(0ll, 0ll))
        ans++;
    }
    if (arr[i] == 1) {
      if (S == MP(0ll, 0ll))
        ans++;
    }
    if (arr[i] == 2) {
      if (S == MP(1ll, 1ll))
        ans++;
    }
    if (arr[i] == 3) {
      if (S == MP((ll)INF - 1, (ll)BIG - 1))
        ans++;
    }
  }
  solve(0, N - 1);
  cout << ans << '\n';
  // when u <, the # divides by co
  // when u >, the # mults by co
  // when u +, u add the #
  // when u -, u subtract the #
  cerr << "time elapsed = " << (clock() / (CLOCKS_PER_SEC / 1000)) << " ms"
       << endl;
  return 0;
}


Fixed submission:
/*
    _____
  .'     '.
 /  0   0  \
|     ^     |
|  \     /  |
 \  '---'  /
  '._____.'
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

struct chash {
  int operator()(int x) const {
    x ^= (x >> 20) ^ (x >> 12);
    return x ^ (x >> 7) ^ (x >> 4);
  }
};

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T, typename U> using hashtable = gp_hash_table<T, U, chash>;
random_device(rd);
mt19937 rng(rd());

template <class T> void readi(T &x) {
  T input = 0;
  bool negative = false;
  char c = ' ';
  while (c < '-') {
    c = getchar();
  }
  if (c == '-') {
    negative = true;
    c = getchar();
  }
  while (c >= '0') {
    input = input * 10 + (c - '0');
    c = getchar();
  }
  if (negative) {
    input = -input;
  }
  x = input;
}
template <class T> void printi(T output) {
  if (output == 0) {
    putchar('0');
    return;
  }
  if (output < 0) {
    putchar('-');
    output = -output;
  }
  int aout[20];
  int ilen = 0;
  while (output) {
    aout[ilen] = ((output % 10));
    output /= 10;
    ilen++;
  }
  for (int i = ilen - 1; i >= 0; i--) {
    putchar(aout[i] + '0');
  }
  return;
}
template <class T> void ckmin(T &a, T b) { a = min(a, b); }
template <class T> void ckmax(T &a, T b) { a = max(a, b); }
template <class T, class U> T nmod(T &x, U mod) {
  if (x >= mod)
    x -= mod;
}
template <class T> T randomize(T mod) {
  return (uniform_int_distribution<T>(0, mod - 1))(rng);
}

#define y0 ___y0
#define y1 ___y1
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second
#define debug(x) cerr << #x << " = " << x << endl;

const long double PI = 4.0 * atan(1.0);
const long double EPS = 1e-10;

#define MAGIC 347
#define SINF 10007
#define CO 1000007
#define INF 1000000007
#define BIG 1000000931
#define LARGE 1696969696967ll
#define GIANT 2564008813937411ll
#define LLINF 2696969696969696969ll
#define MAXN 250013

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;

int N;
int arr[MAXN];
pll S;
long long ans;
map<ll, int> need;

ll expo(ll a, ll e, ll mod) {
  if (e == 0) {
    return 1;
  }
  ll was = expo(a, e / 2, mod);
  if (e % 2) {
    return was * was % mod * a % mod;
  }
  return was * was % mod;
}
ll modinv(ll a, ll e) { return expo(a, e - 2, e); }
pll INV = {modinv(CO, INF), modinv(CO, BIG)};
void solve(int L, int R) {
  if (L == R) {
    return;
  }
  need.clear();
  int mid = (L + R) >> 1;
  // start from L...mid, end at mid + 1....R
  pair<pll, pll> trans = MP(MP(1, 0), MP(1, 0));
  pll inv = MP(1, 1);
  for (int i = mid + 1; i <= R; i++) {
    if (arr[i] == 0) {
      trans.fi.fi *= INV.fi;
      trans.fi.fi %= INF;
      trans.fi.se *= INV.fi;
      trans.fi.se %= INF;
      trans.se.fi *= INV.se;
      trans.se.fi %= BIG;
      trans.se.se *= INV.se;
      trans.se.se %= BIG;
      inv.fi *= CO;
      inv.fi %= INF;
      inv.se *= CO;
      inv.se %= BIG;
    }
    if (arr[i] == 1) {
      trans.fi.fi *= CO;
      trans.fi.fi %= INF;
      trans.fi.se *= CO;
      trans.fi.se %= INF;
      trans.se.fi *= CO;
      trans.se.fi %= BIG;
      trans.se.se *= CO;
      trans.se.se %= BIG;
      inv.fi *= INV.fi;
      inv.fi %= INF;
      inv.se *= INV.se;
      inv.se %= BIG;
    }
    if (arr[i] == 2) {
      trans.fi.se++;
      nmod(trans.fi.se, INF);
      trans.se.se++;
      nmod(trans.se.se, BIG);
    }
    if (arr[i] == 3) {
      trans.fi.se--;
      trans.fi.se += INF;
      nmod(trans.fi.se, INF);
      trans.se.se--;
      trans.se.se += BIG;
      nmod(trans.se.se, BIG);
    }
    pll dif = {(S.fi - trans.fi.se) * inv.fi, (S.se - trans.se.se) * inv.se};
    dif.fi %= INF;
    dif.fi += INF;
    nmod(dif.fi, INF);
    dif.se %= BIG;
    dif.se += BIG;
    nmod(dif.se, BIG);
    need[dif.fi * BIG + dif.se]++;
  }
  trans = MP(MP(1, 0), MP(1, 0));
  for (int i = mid; i >= L; i--) {
    if (arr[i] == 0) {
      trans.fi.fi *= INV.fi;
      trans.fi.fi %= INF;
      trans.se.fi *= INV.se;
      trans.se.fi %= BIG;
    }
    if (arr[i] == 1) {
      trans.fi.fi *= CO;
      trans.fi.fi %= INF;
      trans.se.fi *= CO;
      trans.se.fi %= BIG;
    }
    if (arr[i] == 2) {
      trans.fi.se += trans.fi.fi;
      nmod(trans.fi.se, INF);
      trans.se.se += trans.se.fi;
      nmod(trans.se.se, BIG);
    }
    if (arr[i] == 3) {
      trans.fi.se -= trans.fi.fi;
      trans.fi.se += INF;
      nmod(trans.fi.se, INF);
      trans.se.se -= trans.se.fi;
      trans.se.se += BIG;
      nmod(trans.se.se, BIG);
    }
    ans += need[trans.fi.se * BIG + trans.se.se];
  }
  solve(L, mid);
  solve(mid + 1, R);
}

int32_t main() {
  ios_base::sync_with_stdio(0);
  // cout << fixed << setprecision(10);
  // cerr << fixed << setprecision(10);
  // freopen ("file.in", "r", stdin);
  // freopen ("file.out", "w", stdout);
  cin >> N;
  string temps;
  cin >> temps;
  for (int i = 0; i < N; i++) {
    if (temps[i] == '<') {
      arr[i] = 0;
    }
    if (temps[i] == '>') {
      arr[i] = 1;
    }
    if (temps[i] == '+') {
      arr[i] = 2;
    }
    if (temps[i] == '-') {
      arr[i] = 3;
    }
  }
  reverse(arr, arr + N);
  for (int i = 0; i < N; i++) {
    if (arr[i] == 0) {
      S.fi *= INV.fi;
      S.fi %= INF;
      S.se *= INV.se;
      S.se %= BIG;
    }
    if (arr[i] == 1) {
      S.fi *= CO;
      S.fi %= INF;
      S.se *= CO;
      S.se %= BIG;
    }
    if (arr[i] == 2) {
      S.fi++;
      nmod(S.fi, INF);
      S.se++;
      nmod(S.se, BIG);
    }
    if (arr[i] == 3) {
      S.fi--;
      S.fi += INF;
      nmod(S.fi, INF);
      S.se--;
      S.se += BIG;
      nmod(S.se, BIG);
    }
  }
  for (int i = 0; i < N; i++) {
    if (arr[i] == 0) {
      if (S == MP(0ll, 0ll))
        ans++;
    }
    if (arr[i] == 1) {
      if (S == MP(0ll, 0ll))
        ans++;
    }
    if (arr[i] == 2) {
      if (S == MP(1ll, 1ll))
        ans++;
    }
    if (arr[i] == 3) {
      if (S == MP((ll)INF - 1, (ll)BIG - 1))
        ans++;
    }
  }
  solve(0, N - 1);
  cout << ans << '\n';
  // when u <, the # divides by co
  // when u >, the # mults by co
  // when u +, u add the #
  // when u -, u subtract the #
  cerr << "time elapsed = " << (clock() / (CLOCKS_PER_SEC / 1000)) << " ms"
       << endl;
  return 0;
}