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

#include <algorithm>
#include <climits>
#include <iostream>
#include <vector>

using namespace std;

typedef int64_t llong;

llong mod(llong a, llong b) {
  llong res = a % b;
  if (res >= 0) {
    return res;
  } else {
    return res + b;
  }
}

llong gcd(llong a, llong b) {
  if (b == 0) {
    return a;
  } else {
    return gcd(b, mod(a, b));
  }
}

llong parse(const string &s) {
  llong i = 0;
  llong r = 0;
  while (s[i] != '.' && i < s.size()) {
    llong d = s[i] - '0';
    r = 10 * r + d;
    ++i;
  }
  llong r0 = 1000'000'000 * r;
  ++i;
  r = 0;
  llong cnt = 0;
  while (i < s.size()) {
    llong d = s[i] - '0';
    r = 10 * r + d;
    ++i;
    ++cnt;
  }
  while (cnt < 9) {
    r = 10 * r;
    ++cnt;
  }
  return r0 + r;
}

llong index(const llong &a, const llong &p) {
  llong res = 0;
  llong temp = a;
  while (mod(temp, p) == 0) {
    temp /= p;
    ++res;
  }
  return res;
}

int main() {
  llong n = LLONG_MIN;
  cin >> n;
  vector<llong> a(n);
  vector<vector<llong>> data(19, vector<long>(19));

  for (llong i = 0; i < n; ++i) {
    string s;
    cin >> s;
    a[i] = parse(s);
  }

  llong d9 = 1000000000;
  llong d18 = d9 * d9;
  llong res = 0;

  for (auto e : a) {
    //	cout << e << " " << index(e, 2) << "\\n";
    llong i2 = min(index(e, 2), llong(18));
    llong i5 = min(index(e, 5), llong(18));
    data[i2][i5] = data[i2][i5] + 1;
    llong key = d18 / gcd(d18, e);
    if (mod(e, key) == 0) {
      res -= 1;
    }
  }

  for (int i = 0; i <= 18; ++i) {
    for (int j = 0; j <= 18; ++j) {
      for (int i1 = 0; i1 <= 18; ++i1) {
        for (int j1 = 0; j1 <= 18; ++j1) {
          if (i + i1 >= 18 && j + j1 >= 18) {
            res += data[i][j] * data[i1][j1];
          }
        }
      }
    }
  }
  cout << res / 2 << "\\n";
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <iostream>
#include <set>
#include <vector>

using namespace std;

typedef int64_t llong;

llong mod(llong a, llong b) {
  llong res = a % b;
  if (res >= 0) {
    return res;
  } else {
    return res + b;
  }
}

llong gcd(llong a, llong b) {
  if (b == 0) {
    return a;
  } else {
    return gcd(b, mod(a, b));
  }
}

llong parse(const string &s) {
  llong i = 0;
  llong r = 0;
  while (s[i] != '.' && i < s.size()) {
    llong d = s[i] - '0';
    r = 10 * r + d;
    ++i;
  }
  llong r0 = 1000'000'000 * r;
  ++i;
  r = 0;
  llong cnt = 0;
  while (i < s.size()) {
    llong d = s[i] - '0';
    r = 10 * r + d;
    ++i;
    ++cnt;
  }
  while (cnt < 9) {
    r = 10 * r;
    ++cnt;
  }
  return r0 + r;
}

int main() {
  llong n = LLONG_MIN;
  cin >> n;
  vector<llong> a(n);
  llong t18 = 1 << 18;
  llong d9 = 1000000000;
  llong d18 = d9 * d9;

  vector<vector<llong>> data(t18);

  for (llong i = 0; i < n; ++i) {
    string s;
    cin >> s;
    a[i] = parse(s);
    llong index = mod(a[i], t18);
    data[index].push_back(a[i]);
  }

  llong res = 0;
  for (llong i = 0; i < t18; ++i) {
    if (data[i].size() != 0) {
      for (llong k1 = 0; k1 < data[i].size(); ++k1) {
        llong a = data[i][k1];
        llong b = t18 / gcd(t18, mod(a, t18));
        llong cur = 0;
        llong key = d18 / gcd(d18, a);
        while (cur < t18) {
          for (llong k2 = 0; k2 < data[cur].size(); ++k2) {
            llong c = data[cur][k2];
            if (mod(c, key) == 0 && !(cur == i && k1 == k2)) {
              ++res;
            }
          }
          cur += b;
        }
      }
    }
  }
  cout << res / 2 << "\\n";
}