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

#include <bits/stdc++.h>
using namespace std;

#define rep(i, x, y) for (ll i = (x); i < (y); i++)
#define rrep(i, x, y) for (ll i = (ll)(y)-1; i >= (x); i--)
#define all(x) (x).begin(), (x).end()
#ifdef LOCAL
#define debug(x)                                                               \\
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \\
       << " " << __FILE__ << endl
#define itrdebug(x)                                                            \\
  cerr << #x << " ";                                                           \\
  for (auto &el : (x)) {                                                       \\
    cerr << (el) << " ";                                                       \\
  }                                                                            \\
  cerr << endl
#define dassert(...) assert(__VA_ARGS__)
#else
#define debug(x)
#define itrdebug(x)
#define dassert(...)
#endif
// #define int long long

typedef long long ll;
const ll MOD = 1e9 + 7;
const long double EPS = 1e-8;

long long getGcd(long long a, long long b) {
  if (a < b)
    swap(a, b);
  long long r = a % b;
  while (r != 0) {
    a = b;
    b = r;
    r = a % b;
  }
  return b;
}

namespace mod {
long long pow(long long a, long long x, long long p) {
  long long res = 1;
  while (x > 0) {
    if (x % 2 != 0) {
      res = (res * a) % p;
    }
    a = (a * a) % p;
    x /= 2;
  }
  return res;
}

long long inverse(long long a, long long p) {
  // calculates the modular multiplicative of a mod m.
  //(assuming p is prime).
  return pow(a, p - 2, p);
}

long long factorial(long long a, long long p) {
  long long fact = 1;
  for (long long i = 2; i <= a; i++) {
    fact *= i;
    fact %= p;
  }
  return fact;
}

long long MOD = 1e9 + 7;

template <long long MOD> struct mint {
  long long x;
  mint(long long x = 0) : x((x % MOD + MOD) % MOD) {}
  mint operator-() const { return mint<MOD>(-x); }
  mint &operator+=(const mint<MOD> a) {
    if ((x += a.x) >= MOD)
      x -= MOD;
    return *this;
  }
  mint &operator-=(const mint<MOD> a) {
    if ((x += MOD - a.x) >= MOD)
      x -= MOD;
    return *this;
  }
  mint &operator*=(const mint<MOD> a) {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint operator+(const mint<MOD> a) const { return mint<MOD>(*this) += a; }
  mint operator-(const mint<MOD> a) const { return mint<MOD>(*this) -= a; }
  mint operator*(const mint<MOD> a) const { return mint<MOD>(*this) *= a; }
  mint pow(long long t) const {
    if (!t)
      return 1;
    mint<MOD> a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(MOD - 2); }
  mint &operator/=(const mint<MOD> a) { return *this *= a.inv(); }
  mint operator/(const mint<MOD> a) const { return mint<MOD>(*this) /= a; }
};
} // namespace mod
std::istream &operator>>(std::istream &is, const mod::mint<MOD> &a) {
  return is >> a.x;
}
std::ostream &operator<<(std::ostream &os, const mod::mint<MOD> &a) {
  return os << a.x;
}

struct hash_pair {
  template <class T1, class T2> size_t operator()(const pair<T1, T2> &p) const {
    return p.first ^ p.second;
  }
};

void solve(long long N, std::vector<long long> A, std::vector<long long> B) {
  ll abZeroCnt = 0;
  // unordered_map<pair<ll, ll>, ll, hash_pair> cnt;
  map<pair<ll, ll>, ll> cnt;
  rep(i, 0, N) {
    if (A[i] == 0 && B[i] == 0) {
      abZeroCnt++;
    } else if (A[i] == 0) {
      cnt[{1, 0}]++;
    } else if (B[i] == 0) {
      cnt[{-0, 1}]++;
    } else {
      ll a = A[i], b = B[i];
      ll gcd = getGcd(abs(a), abs(b));
      a /= gcd;
      b /= gcd;
      if (b < 0) {
        a *= -1;
        b *= -1;
      }
      cnt[{a, b}]++;
    }
  }
  mod::mint<MOD> answer = 1;
  for (const auto &el : cnt) {
    ll a = el.first.first, b = el.first.second;
    mod::mint<MOD> current = mod::pow(2, el.second, MOD);
    auto counterpart = a > 0 ? pair<ll, ll>{-b, a} : pair<ll, ll>{b, -a};
    if (cnt.find(counterpart) != cnt.end()) {
      current += mod::pow(2, cnt[counterpart], MOD) - 1;
      cnt.erase(counterpart);
    }
    answer *= current;
  }
  answer += abZeroCnt - 1;
  cout << answer << endl;
}

signed main() {
  // ios_base::sync_with_stdio(false);
  // cin.tie(NULL);
  long long N;
  scanf("%lld", &N);
  std::vector<long long> A(N);
  std::vector<long long> B(N);
  for (int i = 0; i < N; i++) {
    scanf("%lld", &A[i]);
    scanf("%lld", &B[i]);
  }
  solve(N, std::move(A), std::move(B));
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

#define rep(i, x, y) for (ll i = (x); i < (y); i++)
#define rrep(i, x, y) for (ll i = (ll)(y)-1; i >= (x); i--)
#define all(x) (x).begin(), (x).end()
#ifdef LOCAL
#define debug(x)                                                               \\
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \\
       << " " << __FILE__ << endl
#define itrdebug(x)                                                            \\
  cerr << #x << " ";                                                           \\
  for (auto &el : (x)) {                                                       \\
    cerr << (el) << " ";                                                       \\
  }                                                                            \\
  cerr << endl
#define dassert(...) assert(__VA_ARGS__)
#else
#define debug(x)
#define itrdebug(x)
#define dassert(...)
#endif
// #define int long long

typedef long long ll;
const ll MOD = 1e9 + 7;
const long double EPS = 1e-8;

long long getGcd(long long a, long long b) {
  if (a < b)
    swap(a, b);
  long long r = a % b;
  while (r != 0) {
    a = b;
    b = r;
    r = a % b;
  }
  return b;
}

namespace mod {
long long pow(long long a, long long x, long long p) {
  long long res = 1;
  while (x > 0) {
    if (x % 2 != 0) {
      res = (res * a) % p;
    }
    a = (a * a) % p;
    x /= 2;
  }
  return res;
}

long long inverse(long long a, long long p) {
  // calculates the modular multiplicative of a mod m.
  //(assuming p is prime).
  return pow(a, p - 2, p);
}

long long factorial(long long a, long long p) {
  long long fact = 1;
  for (long long i = 2; i <= a; i++) {
    fact *= i;
    fact %= p;
  }
  return fact;
}

long long MOD = 1e9 + 7;

template <long long MOD> struct mint {
  long long x;
  mint(long long x = 0) : x((x % MOD + MOD) % MOD) {}
  mint operator-() const { return mint<MOD>(-x); }
  mint &operator+=(const mint<MOD> a) {
    if ((x += a.x) >= MOD)
      x -= MOD;
    return *this;
  }
  mint &operator-=(const mint<MOD> a) {
    if ((x += MOD - a.x) >= MOD)
      x -= MOD;
    return *this;
  }
  mint &operator*=(const mint<MOD> a) {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint operator+(const mint<MOD> a) const { return mint<MOD>(*this) += a; }
  mint operator-(const mint<MOD> a) const { return mint<MOD>(*this) -= a; }
  mint operator*(const mint<MOD> a) const { return mint<MOD>(*this) *= a; }
  mint pow(long long t) const {
    if (!t)
      return 1;
    mint<MOD> a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(MOD - 2); }
  mint &operator/=(const mint<MOD> a) { return *this *= a.inv(); }
  mint operator/(const mint<MOD> a) const { return mint<MOD>(*this) /= a; }
};
} // namespace mod
std::istream &operator>>(std::istream &is, const mod::mint<MOD> &a) {
  return is >> a.x;
}
std::ostream &operator<<(std::ostream &os, const mod::mint<MOD> &a) {
  return os << a.x;
}

struct hash_pair {
  template <class T1, class T2> size_t operator()(const pair<T1, T2> &p) const {
    return p.first ^ p.second;
  }
};

void solve(long long N, std::vector<long long> A, std::vector<long long> B) {
  ll abZeroCnt = 0;
  unordered_map<pair<ll, ll>, ll, hash_pair> cnt;
  rep(i, 0, N) {
    if (A[i] == 0 && B[i] == 0) {
      abZeroCnt++;
    } else if (A[i] == 0) {
      cnt[{1, 0}]++;
    } else if (B[i] == 0) {
      cnt[{-0, 1}]++;
    } else {
      ll a = A[i], b = B[i];
      ll gcd = getGcd(abs(a), abs(b));
      a /= gcd;
      b /= gcd;
      if (b < 0) {
        a *= -1;
        b *= -1;
      }
      cnt[{a, b}]++;
    }
  }
  mod::mint<MOD> answer = 1;
  for (const auto &el : cnt) {
    ll a = el.first.first, b = el.first.second;
    mod::mint<MOD> current = mod::pow(2, el.second, MOD);
    auto counterpart = a > 0 ? pair<ll, ll>{-b, a} : pair<ll, ll>{b, -a};
    if (cnt.find(counterpart) != cnt.end()) {
      current += mod::pow(2, cnt[counterpart], MOD) - 1;
      cnt.erase(counterpart);
    }
    answer *= current;
  }
  answer += abZeroCnt - 1;
  cout << answer << endl;
}

signed main() {
  // ios_base::sync_with_stdio(false);
  // cin.tie(NULL);
  long long N;
  scanf("%lld", &N);
  std::vector<long long> A(N);
  std::vector<long long> B(N);
  for (int i = 0; i < N; i++) {
    scanf("%lld", &A[i]);
    scanf("%lld", &B[i]);
  }
  solve(N, std::move(A), std::move(B));
  return 0;
}