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

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

// ref.
// https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a#5-%E4%BA%8C%E9%A0%85%E4%BF%82%E6%95%B0-ncr
const int MOD = 1000000007;

// a^n mod を計算する
long long modpow(long long a, long long n) {
  long long res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % MOD;
    a = a * a % MOD;
    n >>= 1;
  }
  return res;
}

int main() {
  int N;
  cin >> N;
  long long num_zero = 0;
  map<pair<long long, long long>, pair<long long, long long>> A;
  for (int ii = 0; ii < N; ii++) {
    long long x, y;
    cin >> x >> y;
    if (x == 0 && y == 0) {
      num_zero++;
      continue;
    }
    long long g = gcd(x, y);
    x /= g;
    y /= g;
    if (y < 0) {
      x = -x;
      y = -y;
    }
    if (y == 0 && x < 0)
      x = -x;
    if (x > 0) {
      A[make_pair(x, y)].first++;
    } else {
      A[make_pair(y, -x)].second++;
    }
  }
  long long ans = 1;
  for (auto a : A) {
    // cout << "(" << a.first.first << ", " << a.first.second << "): " <<
    // a.second.first << ", " << a.second.second << endl;
    ans *= modpow(2, a.second.first) + modpow(2, a.second.second) - 1;
    ans %= MOD;
  }
  ans--;
  ans += MOD;
  ans %= MOD;
  ans += num_zero;
  ans %= MOD;
  cout << ans << endl;
  return 0;
}


Error: TLE

Fixed submission:

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

// ref.
// https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a#5-%E4%BA%8C%E9%A0%85%E4%BF%82%E6%95%B0-ncr
const int MOD = 1000000007;

// a^n mod を計算する
long long modpow(long long a, long long n) {
  long long res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % MOD;
    a = a * a % MOD;
    n >>= 1;
  }
  return res;
}

class UnionFind {

public:
  vector<int> parents;

  UnionFind(int N) : parents(N, -1) {}

  int find(int x) {
    if (this->parents[x] < 0)
      return x;
    return this->parents[x] = this->find(this->parents[x]);
  }

  int size(int x) { return -this->parents[this->find(x)]; }

  void marge(int x, int y) {
    x = this->find(x);
    y = this->find(y);
    if (x == y)
      return;
    if (this->parents[x] > this->parents[y])
      swap(this->parents[x], this->parents[y]);
    this->parents[x] += this->parents[y];
    this->parents[y] = x;
  }

  bool is_same(int x, int y) { return this->find(x) == this->find(y); }

  void check() {
    for (auto &parent : parents)
      cerr << parent << " ";
    cerr << endl;
  }

  int num_union(int lower = 1, int upper = INT_MAX) {
    return count_if(
        this->parents.begin(), this->parents.end(),
        [&](const int &a) { return (lower <= -a) && (-a <= upper); });
  }
};

int main() {
  int N;
  cin >> N;
  vector<vector<long long>> A(N, vector<long long>(2, 0));
  for (auto &a : A) {
    cin >> a[0] >> a[1];
  }
  UnionFind uf(N * 2);
  for (int ii = 0; ii < N; ii++) {
    for (int jj = ii + 1; jj < N; jj++) {
      if (A[ii][0] * A[jj][0] + A[ii][1] * A[jj][1] == 0) {
        uf.marge(ii, N + jj);
        uf.marge(jj, N + ii);
        continue;
      }
    }
  }

  UnionFind uf2(N);
  for (int ii = 0; ii < N; ii++) {
    if (uf.parents[ii] >= 0) {
      uf2.marge(ii, uf.parents[ii]);
    }
  }

  long long ans = 1;
  for (int ii = 0; ii < N; ii++) {
    if (uf.parents[ii] >= 0)
      continue;
    if (uf.parents[ii] == -1) {
      ans *= 2;
      ans %= MOD;
      continue;
    }
    int jj = uf.parents[ii + N];
    if (jj > ii)
      continue;
    ans *= (modpow(2, uf2.size(ii)) + modpow(2, uf2.size(jj)) - 1);
    ans %= MOD;
  }
  cout << (ans - 1) % MOD << endl;
  return 0;
}