Problem p04022 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
using ll = long long;
using ull = unsigned long long;
template <class T = ll> constexpr T TEN(int n) {
  return (n == 0) ? 1 : 10 * TEN<T>(n - 1);
}
template <class T> using V = vector<T>;

struct Prime {
  int n;
  vector<bool> used;
  vector<int> pr;
  vector<ull> bpr;
  Prime(int n) : n(n) {
    used = vector<bool>(n + 1, false);
    for (int i = 2; i <= n; i++) {
      if (used[i])
        continue;
      pr.push_back(i);
      bpr.push_back(((__int128(1) << 64) + i - 1) / i);
      for (int j = 2 * i; j <= n; j += i) {
        used[j] = true;
      }
    }
  }
  map<ll, int> fact(ll x) {
    assert(x <= (ll)n * n);
    int pc = (int)pr.size();
    map<ll, int> mp;
    for (int i = 0; i < pc; i++) {
      ll d = pr[i];
      ull rd = bpr[i];
      //            if (x < d*d) break; 枝刈り
      while (true) {
        ll xd = __int128(x) * rd >> 64;
        if (xd * d != x)
          break;
        x = xd;
        mp[d]++;
      }
    }
    if (x > 1)
      mp[x]++;
    return mp;
  }
};

template <class T> T gcd(T a, T b) {
  //    a = abs(a); b = abs(b);
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

template <class T, class U> T pow_mod(T x, U n, T md) {
  assert(n >= 0);
  x %= md;
  T r = 1 % md;
  while (n) {
    if (n & 1)
      r = (r * x) % md;
    x = (x * x) % md;
    n >>= 1;
  }
  return r;
}

/// g:gcd(a, b), ax+by=g
template <class T> struct EG {
  T g, x, y;
};
template <class T> EG<T> ext_gcd(T a, T b) {
  if (b == 0) {
    if (a >= 0)
      return EG<T>{a, 1, 0};
    else
      return EG<T>{-a, -1, 0};
  } else {
    auto e = ext_gcd<T>(b, a % b);
    return EG<T>{e.g, e.y, e.x - a / b * e.y};
  }
}

template <class T> T inv_mod(T x, T md) {
  auto r = ext_gcd(x, md);
  auto z = r.x;
  return (z % md + md) % md;
}

bool isPrime(ll n) {
  if (n <= 1)
    return false;
  if (n == 2)
    return true;
  if (n % 2 == 0)
    return false;
  ll d = n - 1;
  while (d % 2 == 0)
    d /= 2;
  vector<ll> alist{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; // n < 2^64
  for (ll a : alist) {
    if (n <= a)
      break;
    ll t = d;
    ll y = pow_mod<__int128>(a, t, n); // over
    while (t != n - 1 && y != 1 && y != n - 1) {
      y = __int128(y) * y % n; // flow
      t <<= 1;
    }
    if (y != n - 1 && t % 2 == 0) {
      return false;
    }
  }
  return true;
}

ll f(ll x, ll n) { return __int128_t(x) * x % n + 1 % n; }
ll pollard_single(ll n) {
  ll i, x, y, p;
  if (isPrime(n))
    return n;
  if (!(n & 1))
    return 2;
  for (i = 1; i < 40; i++) {
    x = i;
    y = f(x, n);
    p = gcd(y - x, n);
    while (p == 1) {
      x = f(x, n);
      y = f(f(y, n), n);
      p = gcd((y - x + n) % n, n) % n;
    }
    if (p == 0 || p == n)
      continue;
    return p;
  }
  assert(false);
}

#include <inttypes.h>
#define nelems(x) (sizeof(x) / sizeof((x)[0]))

const int multiplier[] = {1,          3,          5,          7,
                          11,         3 * 5,      3 * 7,      3 * 11,
                          5 * 7,      5 * 11,     7 * 11,     3 * 5 * 7,
                          3 * 5 * 11, 3 * 7 * 11, 5 * 7 * 11, 3 * 5 * 7 * 11};

uint64_t SQUFOF(uint64_t N) {
  if (isPrime(N))
    return N;
  if (N % 2 == 0)
    return 2;
  if (N % 3 == 0)
    return 3;
  if (N % 5 == 0)
    return 5;
  if (N % 7 == 0)
    return 7;
  if (N % 11 == 0)
    return 11;
  uint64_t D, Po, P, Pprev, Q, Qprev, q, b, r, s;
  uint32_t L, B, i;
  s = (uint64_t)(sqrtl(N) + 0.5);
  if (s * s == N)
    return s;
  for (int k = 0; k < nelems(multiplier) && N <= UINT64_MAX / multiplier[k];
       k++) {
    D = multiplier[k] * N;
    Po = Pprev = P = sqrtl(D);
    Qprev = 1;
    Q = D - Po * Po;
    L = 2 * sqrtl(2 * s);
    B = 3 * L;
    for (i = 2; i < B; i++) {
      b = (uint64_t)((Po + P) / Q);
      P = b * Q - P;
      q = Q;
      Q = Qprev + b * (Pprev - P);
      r = (uint64_t)(sqrtl(Q) + 0.5);
      if (!(i & 1) && r * r == Q)
        break;
      Qprev = q;
      Pprev = P;
    };
    if (i >= B)
      continue;
    b = (uint64_t)((Po - P) / r);
    Pprev = P = b * r + P;
    Qprev = r;
    Q = (D - Pprev * Pprev) / Qprev;
    i = 0;
    do {
      b = (uint64_t)((Po + P) / Q);
      Pprev = P;
      P = b * Q - P;
      q = Q;
      Q = Qprev + b * (Pprev - P);
      Qprev = q;
      i++;
    } while (P != Pprev);
    r = gcd(N, Qprev);
    if (r != 1 && r != N)
      return r;
  }
  return 0;
}

V<ll> pollard(ll n) {
  if (n == 1)
    return {};
  ll x;
  //    x = pollard_single(n);
  x = SQUFOF(n);
  if (x == n)
    return {x};
  V<ll> le = pollard(x);
  V<ll> ri = pollard(n / x);
  for (ll d : ri)
    le.push_back(d);
  return le;
}

const int MP = 100100;

ll mul(ll a, ll b) {
  if (TEN(12) / a < b)
    return TEN(12);
  return a * b;
}

int main() {
  Prime pr(MP);
  using P = pair<ll, ll>;
  map<ll, P> g;
  int n;
  scanf("%d", &n);
  bool one = false;
  for (int i = 0; i < n; i++) {
    ll s;
    scanf("%lld", &s);
    auto facv = pollard(s);
    map<ll, int> fac;
    for (auto d : facv)
      fac[d]++;
    //        map<ll, int> fac = pr.fact(s);
    ll d0 = 1, d1 = 1;
    for (auto p : fac) {
      p.second %= 3;
      if (p.second == 1) {
        d0 = mul(d0, p.first);
        d1 = mul(d1, p.first);
        d1 = mul(d1, p.first);
      } else if (p.second == 2) {
        d0 = mul(d0, p.first);
        d0 = mul(d0, p.first);
        d1 = mul(d1, p.first);
      }
    }
    if (d0 == 1) {
      one = true;
      continue;
    }
    if (d0 < d1) {
      g[d0].first++;
    } else {
      g[d1].second++;
    }
  }

  int ans = 0;
  for (auto p : g) {
    ans += max(p.second.first, p.second.second);
  }
  cout << ans + (one ? 1 : 0) << endl;
  return 0;
}


Fixed submission:
#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
using ll = long long;
using ull = unsigned long long;
template <class T = ll> constexpr T TEN(int n) {
  return (n == 0) ? 1 : 10 * TEN<T>(n - 1);
}
template <class T> using V = vector<T>;

struct Prime {
  int n;
  vector<bool> used;
  vector<int> pr;
  vector<ull> bpr;
  Prime(int n) : n(n) {
    used = vector<bool>(n + 1, false);
    for (int i = 2; i <= n; i++) {
      if (used[i])
        continue;
      pr.push_back(i);
      bpr.push_back(((__int128(1) << 64) + i - 1) / i);
      for (int j = 2 * i; j <= n; j += i) {
        used[j] = true;
      }
    }
  }
  map<ll, int> fact(ll x) {
    assert(x <= (ll)n * n);
    int pc = (int)pr.size();
    map<ll, int> mp;
    for (int i = 0; i < pc; i++) {
      ll d = pr[i];
      ull rd = bpr[i];
      //            if (x < d*d) break; 枝刈り
      while (true) {
        ll xd = __int128(x) * rd >> 64;
        if (xd * d != x)
          break;
        x = xd;
        mp[d]++;
      }
    }
    if (x > 1)
      mp[x]++;
    return mp;
  }
};

template <class T> T gcd(T a, T b) {
  //    a = abs(a); b = abs(b);
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

template <class T, class U> T pow_mod(T x, U n, T md) {
  assert(n >= 0);
  x %= md;
  T r = 1 % md;
  while (n) {
    if (n & 1)
      r = (r * x) % md;
    x = (x * x) % md;
    n >>= 1;
  }
  return r;
}

/// g:gcd(a, b), ax+by=g
template <class T> struct EG {
  T g, x, y;
};
template <class T> EG<T> ext_gcd(T a, T b) {
  if (b == 0) {
    if (a >= 0)
      return EG<T>{a, 1, 0};
    else
      return EG<T>{-a, -1, 0};
  } else {
    auto e = ext_gcd<T>(b, a % b);
    return EG<T>{e.g, e.y, e.x - a / b * e.y};
  }
}

template <class T> T inv_mod(T x, T md) {
  auto r = ext_gcd(x, md);
  auto z = r.x;
  return (z % md + md) % md;
}

bool isPrime(ll n) {
  if (n <= 1)
    return false;
  if (n == 2)
    return true;
  if (n % 2 == 0)
    return false;
  ll d = n - 1;
  while (d % 2 == 0)
    d /= 2;
  vector<ll> alist{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; // n < 2^64
  for (ll a : alist) {
    if (n <= a)
      break;
    ll t = d;
    ll y = pow_mod<__int128>(a, t, n); // over
    while (t != n - 1 && y != 1 && y != n - 1) {
      y = __int128(y) * y % n; // flow
      t <<= 1;
    }
    if (y != n - 1 && t % 2 == 0) {
      return false;
    }
  }
  return true;
}

ll f(ll x, ll n) { return __int128_t(x) * x % n + 1 % n; }
ll pollard_single(ll n) {
  ll i, x, y, p;
  if (isPrime(n))
    return n;
  if (!(n & 1))
    return 2;
  for (i = 1; i < 40; i++) {
    x = i;
    y = f(x, n);
    p = gcd(y - x, n);
    while (p == 1) {
      x = f(x, n);
      y = f(f(y, n), n);
      p = gcd((y - x + n) % n, n) % n;
    }
    if (p == 0 || p == n)
      continue;
    return p;
  }
  assert(false);
}

#include <inttypes.h>
#define nelems(x) (sizeof(x) / sizeof((x)[0]))

const int multiplier[] = {1,          3,          5,          7,
                          11,         3 * 5,      3 * 7,      3 * 11,
                          5 * 7,      5 * 11,     7 * 11,     3 * 5 * 7,
                          3 * 5 * 11, 3 * 7 * 11, 5 * 7 * 11, 3 * 5 * 7 * 11};

uint64_t SQUFOF(uint64_t N) {
  if (isPrime(N))
    return N;
  if (N % 2 == 0)
    return 2;
  if (N % 3 == 0)
    return 3;
  if (N % 5 == 0)
    return 5;
  if (N % 7 == 0)
    return 7;
  if (N % 11 == 0)
    return 11;
  uint64_t D, Po, P, Pprev, Q, Qprev, q, b, r, s;
  uint32_t L, B, i;
  s = (uint64_t)(sqrtl(N) + 0.5);
  if (s * s == N)
    return s;
  for (int k = 0; k < nelems(multiplier) && N <= UINT64_MAX / multiplier[k];
       k++) {
    D = multiplier[k] * N;
    Po = Pprev = P = sqrtl(D);
    Qprev = 1;
    Q = D - Po * Po;
    L = 2 * sqrtl(2 * s);
    B = 3 * L;
    for (i = 2; i < B; i++) {
      b = (uint64_t)((Po + P) / Q);
      P = b * Q - P;
      q = Q;
      Q = Qprev + b * (Pprev - P);
      r = (uint64_t)(sqrtl(Q) + 0.5);
      if (!(i & 1) && r * r == Q)
        break;
      Qprev = q;
      Pprev = P;
    };
    if (i >= B)
      continue;
    b = (uint64_t)((Po - P) / r);
    Pprev = P = b * r + P;
    Qprev = r;
    Q = (D - Pprev * Pprev) / Qprev;
    i = 0;
    do {
      b = (uint64_t)((Po + P) / Q);
      Pprev = P;
      P = b * Q - P;
      q = Q;
      Q = Qprev + b * (Pprev - P);
      Qprev = q;
      i++;
    } while (P != Pprev);
    r = gcd(N, Qprev);
    if (r != 1 && r != N)
      return r;
  }
  return pollard_single(N);
  //    cout << "UNTI-KONG" << endl;
  //    exit(0);
  //    return 0;
}

V<ll> pollard(ll n) {
  if (n == 1)
    return {};
  ll x;
  //    x = pollard_single(n);
  x = SQUFOF(n);
  if (x == n)
    return {x};
  V<ll> le = pollard(x);
  V<ll> ri = pollard(n / x);
  for (ll d : ri)
    le.push_back(d);
  return le;
}

const int MP = 100100;

ll mul(ll a, ll b) {
  if (TEN(12) / a < b)
    return TEN(12);
  return a * b;
}

int main() {
  Prime pr(MP);
  using P = pair<ll, ll>;
  map<ll, P> g;
  int n;
  scanf("%d", &n);
  bool one = false;
  for (int i = 0; i < n; i++) {
    ll s;
    scanf("%lld", &s);
    auto facv = pollard(s);
    map<ll, int> fac;
    for (auto d : facv)
      fac[d]++;
    //        map<ll, int> fac = pr.fact(s);
    ll d0 = 1, d1 = 1;
    for (auto p : fac) {
      p.second %= 3;
      if (p.second == 1) {
        d0 = mul(d0, p.first);
        d1 = mul(d1, p.first);
        d1 = mul(d1, p.first);
      } else if (p.second == 2) {
        d0 = mul(d0, p.first);
        d0 = mul(d0, p.first);
        d1 = mul(d1, p.first);
      }
    }
    if (d0 == 1) {
      one = true;
      continue;
    }
    if (d0 < d1) {
      g[d0].first++;
    } else {
      g[d1].second++;
    }
  }

  int ans = 0;
  for (auto p : g) {
    ans += max(p.second.first, p.second.second);
  }
  cout << ans + (one ? 1 : 0) << endl;
  return 0;
}