Problem p04022 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ldb long double
#define ull unsigned long long

map<ull, int> mp, cnt, bo;

ull bin[10000010], hs[100010];
ll a[100010][60], num[100010], ans[233];
int n, tt, tot;

inline ll rd() {
  ll x = 0;
  char ch = getchar();
  for (; ch < '0' || ch > '9'; ch = getchar())
    ;
  for (; ch >= '0' && ch <= '9'; ch = getchar())
    x = x * 10 + ch - '0';
  return x;
}

inline ll gcd(ll x, ll y) { return (!y) ? x : gcd(y, x % y); }

inline ll tms(ll x, ll y, ll p) {
  ll hh = (ldb)x / p * y + 1e-3;
  return ((x * y - hh * p) % p + p) % p;
}

inline ll ksm(ll x, ll y, ll p) {
  ll res = 1;
  for (; y; y >>= 1, x = tms(x, x, p))
    if (y & 1)
      res = tms(res, x, p);
  return res;
}

inline bool check(ll x, ll y, ll z, ll n) {
  ll hh = ksm(x, y, n), now = hh;
  for (ll i = 1; i <= z; i++) {
    hh = tms(hh, hh, n);
    if (hh == 1 && now != 1 && now != n - 1)
      return true;
    now = hh;
  }
  if (hh != 1)
    return true;
  return false;
}

inline bool miller_rabin(ll n) {
  if (n == 4759123141LL)
    return false;
  if (n == 2)
    return true;
  if (n % 2 == 0)
    return false;
  ll hh = n - 1, hhh = 0;
  while (hh % 2 == 0)
    hh >>= 1, hhh++;
  if (check(7, hh, hhh, n))
    return false;
  if (check(61, hh, hhh, n))
    return false;
  return true;
}

inline ll pollard_rho(ll a, ll n) {
  ll k = 2, x = (ll)rand() * rand() % n, y = x, p = 1;
  for (ll i = 1; p == 1; i++) {
    x = (tms(x, x, n) + a) % n;
    p = gcd(n, abs(x - y));
    if (i == k)
      y = x, k <<= 1;
  }
  return p;
}

inline void find_fac(ll n) {
  if (n == 1)
    return;
  if (miller_rabin(n)) {
    ans[++tot] = n;
    return;
  }
  ll hh = n;
  while (hh == n)
    hh = pollard_rho((ll)rand() * rand() % (n - 1) + 1, n);
  find_fac(hh);
  find_fac(n / hh);
}

int main() {
  srand(19260817);
  n = rd();
  tt = 0;
  for (int i = 1; i <= n; i++)
    num[i] = rd();
  bin[1] = 1;
  for (int i = 2; i <= 10000000; i++)
    bin[i] = bin[i - 1] * 233ull;
  for (int i = 1; i <= n; i++) {
    if (num[i] == 1) {
      a[i][0] = 0;
      continue;
    }
    tot = 0;
    find_fac(num[i]);
    sort(ans + 1, ans + tot + 1);
    ans[tot + 1] = -1;
    ull now = 0;
    for (int j = 1; j <= tot;) {
      int k = j;
      for (; ans[k] == ans[j]; k++)
        ;
      k--;
      int hh = (k - j + 1) % 3;
      if (!mp[ans[j]])
        mp[ans[j]] = ++tt;
      now += (ull)bin[mp[ans[j]]] * (ull)hh;
      j = k + 1;
    }
    cnt[now]++;
    hs[i] = now;
    a[i][0] = tot;
    for (int j = 1; j <= tot; j++)
      a[i][j] = ans[j];
  }
  int res = 0;
  bool flag = false;
  for (int i = 1; i <= n; i++) {
    if (bo[hs[i]])
      continue;
    bo[hs[i]] = true;
    if (!hs[i]) {
      flag = true;
      continue;
    }
    tot = a[i][0];
    for (int j = 1; j <= tot; j++)
      ans[j] = a[i][j];
    ans[tot + 1] = -1;
    ull now = 0;
    for (int j = 1; j <= tot;) {
      int k = j;
      for (; ans[k] == ans[j]; k++)
        ;
      k--;
      int hh = (k - j + 1) % 3;
      if (hh == 0)
        hh = 0;
      else if (hh == 1)
        hh = 2;
      else
        hh = 1;
      now += (ull)bin[mp[ans[j]]] * (ull)hh;
      j = k + 1;
    }
    bo[now] = true;
    if (cnt[hs[i]] > cnt[now])
      res += cnt[hs[i]];
    else if (cnt[hs[i]] == cnt[now])
      res += cnt[hs[i]];
    else
      res += cnt[now];
  }
  printf("%d\n", res + flag);
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ldb long double
#define ull unsigned long long

map<ull, int> mp, cnt, bo;

ull bin[10000010], hs[100010];
ll a[100010][60], num[100010], ans[233];
int n, tt, tot;

inline ll rd() {
  ll x = 0;
  char ch = getchar();
  for (; ch < '0' || ch > '9'; ch = getchar())
    ;
  for (; ch >= '0' && ch <= '9'; ch = getchar())
    x = x * 10 + ch - '0';
  return x;
}

inline ll gcd(ll x, ll y) { return (!y) ? x : gcd(y, x % y); }

inline ll tms(ll x, ll y, ll p) {
  ll hh = (ldb)x / p * y + 1e-3;
  return ((x * y - hh * p) % p + p) % p;
}

inline ll ksm(ll x, ll y, ll p) {
  ll res = 1;
  for (; y; y >>= 1, x = tms(x, x, p))
    if (y & 1)
      res = tms(res, x, p);
  return res;
}

inline bool check(ll x, ll y, ll z, ll n) {
  ll hh = ksm(x, y, n), now = hh;
  for (ll i = 1; i <= z; i++) {
    hh = tms(hh, hh, n);
    if (hh == 1 && now != 1 && now != n - 1)
      return true;
    now = hh;
  }
  if (hh != 1)
    return true;
  return false;
}

inline bool miller_rabin(ll n) {
  if (n == 4759123141LL)
    return false;
  if (n == 2)
    return true;
  if (n == 7)
    return true;
  if (n == 61)
    return true;
  if (n % 2 == 0)
    return false;
  ll hh = n - 1, hhh = 0;
  while (hh % 2 == 0)
    hh >>= 1, hhh++;
  if (check(7, hh, hhh, n))
    return false;
  if (check(61, hh, hhh, n))
    return false;
  return true;
}

inline ll pollard_rho(ll a, ll n) {
  ll k = 2, x = (ll)rand() * rand() % n, y = x, p = 1;
  for (ll i = 1; p == 1; i++) {
    x = (tms(x, x, n) + a) % n;
    p = gcd(n, abs(x - y));
    if (i == k)
      y = x, k <<= 1;
  }
  return p;
}

inline void find_fac(ll n) {
  if (n == 1)
    return;
  if (miller_rabin(n)) {
    ans[++tot] = n;
    return;
  }
  ll hh = n;
  while (hh == n)
    hh = pollard_rho((ll)rand() * rand() % (n - 1) + 1, n);
  find_fac(hh);
  find_fac(n / hh);
}

int main() {
  srand(19260817);
  n = rd();
  tt = 0;
  for (int i = 1; i <= n; i++)
    num[i] = rd();
  bin[1] = 1;
  for (int i = 2; i <= 10000000; i++)
    bin[i] = bin[i - 1] * 233ull;
  for (int i = 1; i <= n; i++) {
    if (num[i] == 1) {
      a[i][0] = 0;
      continue;
    }
    tot = 0;
    find_fac(num[i]);
    sort(ans + 1, ans + tot + 1);
    ans[tot + 1] = -1;
    ull now = 0;
    for (int j = 1; j <= tot;) {
      int k = j;
      for (; ans[k] == ans[j]; k++)
        ;
      k--;
      int hh = (k - j + 1) % 3;
      if (!mp[ans[j]])
        mp[ans[j]] = ++tt;
      now += (ull)bin[mp[ans[j]]] * (ull)hh;
      j = k + 1;
    }
    cnt[now]++;
    hs[i] = now;
    a[i][0] = tot;
    for (int j = 1; j <= tot; j++)
      a[i][j] = ans[j];
  }
  int res = 0;
  bool flag = false;
  for (int i = 1; i <= n; i++) {
    if (bo[hs[i]])
      continue;
    bo[hs[i]] = true;
    if (!hs[i]) {
      flag = true;
      continue;
    }
    tot = a[i][0];
    for (int j = 1; j <= tot; j++)
      ans[j] = a[i][j];
    ans[tot + 1] = -1;
    ull now = 0;
    for (int j = 1; j <= tot;) {
      int k = j;
      for (; ans[k] == ans[j]; k++)
        ;
      k--;
      int hh = (k - j + 1) % 3;
      if (hh == 0)
        hh = 0;
      else if (hh == 1)
        hh = 2;
      else
        hh = 1;
      now += (ull)bin[mp[ans[j]]] * (ull)hh;
      j = k + 1;
    }
    bo[now] = true;
    if (cnt[hs[i]] > cnt[now])
      res += cnt[hs[i]];
    else if (cnt[hs[i]] == cnt[now])
      res += cnt[hs[i]];
    else
      res += cnt[now];
  }
  printf("%d\n", res + flag);
  return 0;
}