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

//////// Coprime
// https://atcoder.jp/contests/abc177/tasks/abc177_e
// date: 2020-08-29T21:00:28.779732
// memo:

//<editor-fold desc="my macro">

#include <bits/stdc++.h>
#ifdef LOCAL
#include <my/dump.h>
#else
#define dump(...) 42
#define dumpi(x) 42
#endif

typedef long long ll;
using namespace std;

#define repe(x, a) for (auto &(x) : (a))
#define _overload3(_1, _2, _3, name, ...) name
#define rep(...) _overload3(__VA_ARGS__, _rep3, _rep2, )(__VA_ARGS__)
#define _rep3(i, a, b) for (ll i = a, i##_len = (b); i < i##_len; i++)
#define _rep2(i, n) _rep3(i, 0, n)
#define repd(...) _overload3(__VA_ARGS__, _repd3, _repd2, )(__VA_ARGS__)
#define _repd3(i, a, b) for (ll i = b - 1, i##_len = (a); i >= i##_len; i--)
#define _repd2(i, n) _repd3(i, 0, n)
#define loop(...) _overload3(__VA_ARGS__, , _loop2, _loop1)(__VA_ARGS__)
#define _loop2(i, a) for (ll i = a;; i++)
#define _loop1(i) _loop2(i, 0)

#define all(x) x.begin(), x.end()
#define SIZE(x) ((ll)(x).size())

#define F first
#define S second
#define vec vector
#define umap unordered_map
#define uset unordered_set

ll dx[4] = {1, 0, -1, 0};
ll dy[4] = {0, 1, 0, -1};

#define bit(n) (1LL << (n))
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());

#define inrange(x, start, stop) ((start) <= (x) && (x) < (stop))
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

template <typename Cont, typename Func>
Cont fmap(const Cont &container, Func functor) {
  Cont result(container.size());
  std::transform(container.begin(), container.end(), result.begin(),
                 functor); // [](int x){return x * 2;}
  return result;
}
template <typename Cont, typename Pred>
Cont filter(const Cont &container, Pred predicate) {
  Cont result;
  std::copy_if(container.begin(), container.end(), std::back_inserter(result),
               predicate); // [](int x){return x == 2;}
  return result;
}

template <typename T, typename... Args> void ci(T &first, Args &...args) {
  ((cin >> first), ..., (cin >> args)); // C++17
}

template <char Sep, typename T, typename... Args>
void print_seq(const T &first, const Args &...args) {
  ((cout << first), ..., (cout << Sep << args)); // C++17
}

void co() { cout << endl; }
template <typename... Words> void co(Words... words) {
  print_seq<' '>(words...);
  cout << endl;
}
#define coi(x) cout << (x) << " "

#define YES(n) cout << ((n) ? "YES" : "NO") << endl
#define Yes(n) cout << ((n) ? "Yes" : "No") << endl
#define sankou(n, a, b) cout << ((n) ? (a) : (b)) << endl

#define asrt(expr...) assert((expr))
//</editor-fold>

#define INF 1e19
#define MOD 1e9 + 7
#define MAXR 1e5

#define MAXPRIME 1000005
#define MAXISPRIME 1005

int solve() {
  ll n;
  ci(n);
  vec<ll> a;
  rep(i, n) {
    ll buf;
    ci(buf);
    a.push_back(buf);
  }
  dump(n);
  dump(a);

  // 1005までの2以上の素数列,primesを計算
  bool isprime[MAXPRIME];
  rep(i, MAXPRIME) isprime[i] = true;
  isprime[0] = false;
  isprime[1] = false;
  rep(i, 2, MAXPRIME) {
    rep(j, 2, MAXPRIME / i) {
      if (i * j > MAXPRIME)
        continue;
      isprime[i * j] = false;
    }
  }
  vec<ll> primes;
  rep(i, MAXPRIME) {
    if (isprime[i])
      primes.push_back(i);
    if (i > (MAXPRIME / 2 + 10))
      break;
  }
  dump(primes.size());

  uset<ll> prime_intersection; // 因数の積集合
  repe(p, primes) {
    if (a[0] % p == 0) {
      prime_intersection.insert(p);
    }
  }

  uset<ll> prime_union; // 今ままであった素数をindexで登録
  bool setwise = false; // 今まであった素数が存在したかのフラグ
  rep(i, n) {
    // 1の場合早めに切り上げ
    if (a[i] == 1) {
      prime_intersection.clear();
      continue;
    }
    // 素数の場合早めに切り上げ
    if (isprime[a[i]]) {
      ll p = a[i];
      // 積集合
      if (prime_intersection.count(p)) {
        prime_intersection.clear();
        prime_intersection.insert(p);
      } else {
        prime_intersection.clear();
      }
      // 和集合
      if (prime_union.count(p)) {
        // すでに登録された因子
        setwise = true;
      } else {
        // なければ因子を登録する
        prime_union.insert(p);
      }
      continue;
    }

    // 積集合の計算
    vec<ll> removes;
    repe(p, prime_intersection) {
      // 割り切れなければ、積集合から削除
      if (a[i] % p)
        removes.push_back(p);
    }
    repe(r, removes) prime_intersection.erase(r);

    // 和集合の計算
    ll buf = a[i];
    repe(p, primes) {
      if (buf < p)
        break;
      if (buf % p == 0) {
        while (buf % p == 0)
          buf /= p;
        if (prime_union.count(p)) {
          // すでに登録された因子
          setwise = true;
        } else {
          // なければ因子を登録する
          prime_union.insert(p);
        }
      }
    }
  }

  if (!prime_intersection.empty()) {
    // 共通因子がある
    co("not coprime");
    return 0;
  }

  if (setwise) {
    co("setwise coprime");
  } else {
    // 一つも因子がかぶらなかった
    co("pairwise coprime");
  }
  return 0;
}

int solve2() {
  ll n;
  ci(n);
  vec<ll> a;
  rep(i, n) {
    ll buf;
    ci(buf);
    a.push_back(buf);
  }
  dump(n);
  dump(a);

  // 1005までの2以上の素数列,primesを計算
  bool isprime[MAXPRIME];
  rep(i, MAXPRIME) isprime[i] = true;
  isprime[0] = false;
  isprime[1] = false;
  rep(i, 2, MAXPRIME) {
    rep(j, 2, MAXPRIME / i) {
      if (i * j > MAXPRIME)
        continue;
      isprime[i * j] = false;
    }
  }
  vec<ll> primes;
  rep(i, MAXPRIME) {
    if (isprime[i])
      primes.push_back(i);
    if (i > (MAXPRIME / 2 + 10))
      break;
  }
  dump(primes.size());

  uset<ll> prime_intersection; // 因数の積集合
  repe(p, primes) {
    if (a[0] % p == 0) {
      prime_intersection.insert(p);
    }
  }

  uset<ll> prime_union; // 今ままであった素数をindexで登録
  bool setwise = false; // 今まであった素数が存在したかのフラグ
  rep(i, n) {
    // 1の場合早めに切り上げ
    if (a[i] == 1) {
      prime_intersection.clear();
      continue;
    }
    // 素数の場合早めに切り上げ
    if (isprime[a[i]]) {
      ll p = a[i];
      // 積集合
      if (prime_intersection.count(p)) {
        prime_intersection.clear();
        prime_intersection.insert(p);
      } else {
        prime_intersection.clear();
      }
      // 和集合
      if (prime_union.count(p)) {
        // すでに登録された因子
        setwise = true;
      } else {
        // なければ因子を登録する
        prime_union.insert(p);
      }
      continue;
    }

    // 積集合の計算
    vec<ll> removes;
    repe(p, prime_intersection) {
      // 割り切れなければ、積集合から削除
      if (a[i] % p)
        removes.push_back(p);
    }
    repe(r, removes) prime_intersection.erase(r);

    // 和集合の計算
    ll buf = a[i];
    repe(p, primes) {
      if (buf < p)
        break;
      if (buf % p == 0) {
        while (buf % p == 0)
          buf /= p;
        if (prime_union.count(p)) {
          // すでに登録された因子
          setwise = true;
        } else {
          // なければ因子を登録する
          prime_union.insert(p);
        }
      }
    }
  }

  if (!prime_intersection.empty()) {
    // 共通因子がある
    co("not coprime");
    return 0;
  }

  if (setwise) {
    co("setwise coprime");
  } else {
    // 一つも因子がかぶらなかった
    co("pairwise coprime");
  }
  return 0;
}

void solve3() {
  ll n;
  ci(n);
  vec<ll> a;
  rep(i, n) {
    ll buf;
    ci(buf);
    a.push_back(buf);
  }
  dump(n);
  dump(a);

  vec<vec<ll>> primelist;
  bool isplime[MAXPRIME];
  rep(i, MAXPRIME) primelist.emplace_back();
  rep(i, 2, MAXPRIME) {
    if (!primelist[i].empty())
      continue;
    rep(j, 1, MAXPRIME / i + 1) {
      if (i * j > MAXPRIME)
        break;
      primelist[i * j].push_back(i);
    }
  }

  uset<ll> prime_union;        // 因数の和集合
  uset<ll> prime_intersection; // 因数の積集合
  repe(p, primelist[a[0]]) prime_intersection.insert(p);
  bool setwise = false;

  rep(i, n) {
    ll target = a[i];
    // 1の場合早めに切り上げ
    if (target == 1) {
      prime_intersection.clear();
      continue;
    }

    auto primes = primelist[target];
    // 積集合の計算
    if (!prime_intersection.empty()) {
      uset<ll> keep;
      repe(p, primes) {
        if (prime_intersection.count(p))
          keep.insert(p);
      }
      prime_intersection = keep;
    }

    // 和集合の計算
    repe(p, primes) {
      if (prime_union.count(p)) {
        // すでに登録された因子
        setwise = true;
      } else {
        // なければ因子を登録する
        prime_union.insert(p);
      }
    }

    // 共通因子ゼロの場合、早めに切り上げ
    if (prime_intersection.empty() && setwise) {
      co("setwise coprime");
      return;
    }
  }

  if (!prime_intersection.empty()) {
    // 全部に共通な因子がある
    co("not coprime");
    dump(prime_intersection);
    return;
  }

  if (setwise) {
    // あるペアで共通因子が存在する
    co("setwise coprime");
  } else {
    // 一つも因子がかぶらなかった
    co("pairwise coprime");
  }
}

int main() {
  // 入力の高速化用のコード
  // ios::sync_with_stdio(false);
  // cin.tie(nullptr);

  solve3();
  return 0;
}


Error: TLE

Fixed submission:

//////// Coprime
// https://atcoder.jp/contests/abc177/tasks/abc177_e
// date: 2020-08-29T21:00:28.779732
// memo:

//<editor-fold desc="my macro">

#include <bits/stdc++.h>
#ifdef LOCAL
#include <my/dump.h>
#else
#define dump(...) 42
#define dumpi(x) 42
#endif

typedef long long ll;
using namespace std;

#define repe(x, a) for (auto &(x) : (a))
#define _overload3(_1, _2, _3, name, ...) name
#define rep(...) _overload3(__VA_ARGS__, _rep3, _rep2, )(__VA_ARGS__)
#define _rep3(i, a, b) for (ll i = a, i##_len = (b); i < i##_len; i++)
#define _rep2(i, n) _rep3(i, 0, n)
#define repd(...) _overload3(__VA_ARGS__, _repd3, _repd2, )(__VA_ARGS__)
#define _repd3(i, a, b) for (ll i = b - 1, i##_len = (a); i >= i##_len; i--)
#define _repd2(i, n) _repd3(i, 0, n)
#define loop(...) _overload3(__VA_ARGS__, , _loop2, _loop1)(__VA_ARGS__)
#define _loop2(i, a) for (ll i = a;; i++)
#define _loop1(i) _loop2(i, 0)

#define all(x) x.begin(), x.end()
#define SIZE(x) ((ll)(x).size())

#define F first
#define S second
#define vec vector
#define umap unordered_map
#define uset unordered_set

ll dx[4] = {1, 0, -1, 0};
ll dy[4] = {0, 1, 0, -1};

#define bit(n) (1LL << (n))
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());

#define inrange(x, start, stop) ((start) <= (x) && (x) < (stop))
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

template <typename Cont, typename Func>
Cont fmap(const Cont &container, Func functor) {
  Cont result(container.size());
  std::transform(container.begin(), container.end(), result.begin(),
                 functor); // [](int x){return x * 2;}
  return result;
}
template <typename Cont, typename Pred>
Cont filter(const Cont &container, Pred predicate) {
  Cont result;
  std::copy_if(container.begin(), container.end(), std::back_inserter(result),
               predicate); // [](int x){return x == 2;}
  return result;
}

template <typename T, typename... Args> void ci(T &first, Args &...args) {
  ((cin >> first), ..., (cin >> args)); // C++17
}

template <char Sep, typename T, typename... Args>
void print_seq(const T &first, const Args &...args) {
  ((cout << first), ..., (cout << Sep << args)); // C++17
}

void co() { cout << endl; }
template <typename... Words> void co(Words... words) {
  print_seq<' '>(words...);
  cout << endl;
}
#define coi(x) cout << (x) << " "

#define YES(n) cout << ((n) ? "YES" : "NO") << endl
#define Yes(n) cout << ((n) ? "Yes" : "No") << endl
#define sankou(n, a, b) cout << ((n) ? (a) : (b)) << endl

#define asrt(expr...) assert((expr))
//</editor-fold>

#define INF 1e19
#define MOD 1e9 + 7
#define MAXR 1e5

#define MAXPRIME 1000005
#define MAXISPRIME 1005

int solve() {
  ll n;
  ci(n);
  vec<ll> a;
  rep(i, n) {
    ll buf;
    ci(buf);
    a.push_back(buf);
  }
  dump(n);
  dump(a);

  // 1005までの2以上の素数列,primesを計算
  bool isprime[MAXPRIME];
  rep(i, MAXPRIME) isprime[i] = true;
  isprime[0] = false;
  isprime[1] = false;
  rep(i, 2, MAXPRIME) {
    rep(j, 2, MAXPRIME / i) {
      if (i * j > MAXPRIME)
        continue;
      isprime[i * j] = false;
    }
  }
  vec<ll> primes;
  rep(i, MAXPRIME) {
    if (isprime[i])
      primes.push_back(i);
    if (i > (MAXPRIME / 2 + 10))
      break;
  }
  dump(primes.size());

  uset<ll> prime_intersection; // 因数の積集合
  repe(p, primes) {
    if (a[0] % p == 0) {
      prime_intersection.insert(p);
    }
  }

  uset<ll> prime_union; // 今ままであった素数をindexで登録
  bool setwise = false; // 今まであった素数が存在したかのフラグ
  rep(i, n) {
    // 1の場合早めに切り上げ
    if (a[i] == 1) {
      prime_intersection.clear();
      continue;
    }
    // 素数の場合早めに切り上げ
    if (isprime[a[i]]) {
      ll p = a[i];
      // 積集合
      if (prime_intersection.count(p)) {
        prime_intersection.clear();
        prime_intersection.insert(p);
      } else {
        prime_intersection.clear();
      }
      // 和集合
      if (prime_union.count(p)) {
        // すでに登録された因子
        setwise = true;
      } else {
        // なければ因子を登録する
        prime_union.insert(p);
      }
      continue;
    }

    // 積集合の計算
    vec<ll> removes;
    repe(p, prime_intersection) {
      // 割り切れなければ、積集合から削除
      if (a[i] % p)
        removes.push_back(p);
    }
    repe(r, removes) prime_intersection.erase(r);

    // 和集合の計算
    ll buf = a[i];
    repe(p, primes) {
      if (buf < p)
        break;
      if (buf % p == 0) {
        while (buf % p == 0)
          buf /= p;
        if (prime_union.count(p)) {
          // すでに登録された因子
          setwise = true;
        } else {
          // なければ因子を登録する
          prime_union.insert(p);
        }
      }
    }
  }

  if (!prime_intersection.empty()) {
    // 共通因子がある
    co("not coprime");
    return 0;
  }

  if (setwise) {
    co("setwise coprime");
  } else {
    // 一つも因子がかぶらなかった
    co("pairwise coprime");
  }
  return 0;
}

int solve2() {
  ll n;
  ci(n);
  vec<ll> a;
  rep(i, n) {
    ll buf;
    ci(buf);
    a.push_back(buf);
  }
  dump(n);
  dump(a);

  // 1005までの2以上の素数列,primesを計算
  bool isprime[MAXPRIME];
  rep(i, MAXPRIME) isprime[i] = true;
  isprime[0] = false;
  isprime[1] = false;
  rep(i, 2, MAXPRIME) {
    rep(j, 2, MAXPRIME / i) {
      if (i * j > MAXPRIME)
        continue;
      isprime[i * j] = false;
    }
  }
  vec<ll> primes;
  rep(i, MAXPRIME) {
    if (isprime[i])
      primes.push_back(i);
    if (i > (MAXPRIME / 2 + 10))
      break;
  }
  dump(primes.size());

  uset<ll> prime_intersection; // 因数の積集合
  repe(p, primes) {
    if (a[0] % p == 0) {
      prime_intersection.insert(p);
    }
  }

  uset<ll> prime_union; // 今ままであった素数をindexで登録
  bool setwise = false; // 今まであった素数が存在したかのフラグ
  rep(i, n) {
    // 1の場合早めに切り上げ
    if (a[i] == 1) {
      prime_intersection.clear();
      continue;
    }
    // 素数の場合早めに切り上げ
    if (isprime[a[i]]) {
      ll p = a[i];
      // 積集合
      if (prime_intersection.count(p)) {
        prime_intersection.clear();
        prime_intersection.insert(p);
      } else {
        prime_intersection.clear();
      }
      // 和集合
      if (prime_union.count(p)) {
        // すでに登録された因子
        setwise = true;
      } else {
        // なければ因子を登録する
        prime_union.insert(p);
      }
      continue;
    }

    // 積集合の計算
    vec<ll> removes;
    repe(p, prime_intersection) {
      // 割り切れなければ、積集合から削除
      if (a[i] % p)
        removes.push_back(p);
    }
    repe(r, removes) prime_intersection.erase(r);

    // 和集合の計算
    ll buf = a[i];
    repe(p, primes) {
      if (buf < p)
        break;
      if (buf % p == 0) {
        while (buf % p == 0)
          buf /= p;
        if (prime_union.count(p)) {
          // すでに登録された因子
          setwise = true;
        } else {
          // なければ因子を登録する
          prime_union.insert(p);
        }
      }
    }
  }

  if (!prime_intersection.empty()) {
    // 共通因子がある
    co("not coprime");
    return 0;
  }

  if (setwise) {
    co("setwise coprime");
  } else {
    // 一つも因子がかぶらなかった
    co("pairwise coprime");
  }
  return 0;
}

void solve3() {
  ll n;
  ci(n);
  vec<ll> a;
  rep(i, n) {
    ll buf;
    ci(buf);
    a.push_back(buf);
  }
  dump(n);
  dump(a);

  vec<vec<ll>> primelist;
  rep(i, MAXPRIME) primelist.emplace_back();
  rep(i, 2, MAXPRIME) {
    rep(j, 1, MAXPRIME / i + 1) {
      if (i * j > MAXPRIME)
        break;
      primelist[i * j].push_back(i);
    }
  }

  uset<ll> prime_union;        // 因数の和集合
  uset<ll> prime_intersection; // 因数の積集合
  repe(p, primelist[a[0]]) prime_intersection.insert(p);
  bool setwise = false;

  rep(i, n) {
    // 1の場合早めに切り上げ
    if (a[i] == 1) {
      prime_intersection.clear();
      continue;
    }

    auto primes = primelist[a[i]];
    // 積集合の計算
    if (!prime_intersection.empty()) {
      uset<ll> keep;
      repe(p, primes) {
        if (prime_intersection.count(p))
          keep.insert(p);
      }
      prime_intersection = keep;
    }

    // 和集合の計算
    repe(p, primes) {
      if (prime_union.count(p)) {
        // すでに登録された因子
        setwise = true;
      } else {
        // なければ因子を登録する
        prime_union.insert(p);
      }
    }

    // 共通因子ゼロの場合、早めに切り上げ
    if (prime_intersection.empty() && setwise) {
      co("setwise coprime");
      return;
    }
  }

  if (!prime_intersection.empty()) {
    // 全部に共通な因子がある
    co("not coprime");
    dump(prime_intersection);
    return;
  }

  if (setwise) {
    // あるペアで共通因子が存在する
    co("setwise coprime");
  } else {
    // 一つも因子がかぶらなかった
    co("pairwise coprime");
  }
}

int main() {
  // 入力の高速化用のコード
  // ios::sync_with_stdio(false);
  // cin.tie(nullptr);

  solve3();
  return 0;
}