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

#include <iostream>
#include <map>
#include <utility>

using namespace std;

const long long MOD = 1000000007;

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

// c^n
long long modpow(long long c, long long n) {
  long long ret = 1;
  while (n != 0) {
    if (n & 1) {
      ret = ret * c % MOD;
    }
    c = c * c % MOD;
    n /= 2;
  }
  return ret;
}

int main() {
  long long N;
  cin >> N;

  long long zero_zero = 0, l_zero = 0, r_zero = 0;
  map<pair<long long, long long>, long long> M;
  for (int i = 0; i < N; i++) {
    long long A, B;
    cin >> A >> B;

    if (A == 0 && B == 0) {
      zero_zero++;
    } else if (A == 0) {
      l_zero++;
    } else if (B == 0) {
      r_zero++;
    } else {
      if (B == 0) {
        M[make_pair(1, 0)]++;
      } else if (B > 0) {
        long long gcd = euclid_gcd(abs(A), abs(B));
        A /= gcd;
        B /= gcd;
        M[make_pair(A, B)]++;
      } else {
        long long gcd = euclid_gcd(abs(A), abs(B));
        A /= -gcd;
        B /= -gcd;
        M[make_pair(A, B)]++;
      }
    }
  }

  long long ans = 1;
  if (l_zero != 0 || r_zero != 0) {
    ans *= (modpow(2, l_zero) + modpow(2, r_zero) - 1 + MOD) % MOD;
  }
  for (auto m : M) {
    long long n = M[m.first];
    if (n == 0) {
      continue;
    }

    auto counterpart = make_pair(m.first.second, m.first.first);
    if (counterpart.second < 0) {
      counterpart.second *= -1;
    } else {
      counterpart.first *= -1;
    }

    long long n_counterpart = M[counterpart];
    M[counterpart] = 0;
    if (n_counterpart != 0) {
      ans *= ((modpow(2, n) + modpow(2, n_counterpart)) % MOD - 1 + MOD) % MOD;
      ans %= MOD;
    } else {
      ans *= modpow(2, n);
      ans %= MOD;
    }
  }

  cout << (ans + zero_zero - 1 + MOD) % MOD << endl;
  return 0;
}


Error: TLE

Fixed submission:

#include <iostream>
#include <map>
#include <utility>

using namespace std;

const long long MOD = 1000000007;

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

// c^n
long long modpow(long long c, long long n) {
  long long ret = 1;
  while (n != 0) {
    if (n & 1) {
      ret = ret * c % MOD;
    }
    c = c * c % MOD;
    n /= 2;
  }
  return ret;
}

int main() {
  long long N;
  cin >> N;

  long long zero_zero = 0, l_zero = 0, r_zero = 0;
  map<pair<long long, long long>, long long> M;
  for (int i = 0; i < N; i++) {
    long long A, B;
    cin >> A >> B;

    if (A == 0 && B == 0) {
      zero_zero++;
    } else if (A == 0) {
      l_zero++;
    } else if (B == 0) {
      r_zero++;
    } else {
      if (B == 0) {
        M[make_pair(1, 0)]++;
      } else if (B > 0) {
        long long gcd = euclid_gcd(abs(A), abs(B));
        A /= gcd;
        B /= gcd;
        M[make_pair(A, B)]++;
      } else {
        long long gcd = euclid_gcd(abs(A), abs(B));
        A /= -gcd;
        B /= -gcd;
        M[make_pair(A, B)]++;
      }
    }
  }

  long long ans = 1;
  if (l_zero != 0 || r_zero != 0) {
    ans *= (modpow(2, l_zero) + modpow(2, r_zero) - 1 + MOD) % MOD;
  }
  for (auto m : M) {
    long long n = M[m.first];
    if (n == 0) {
      continue;
    }

    auto counterpart = make_pair(m.first.second, m.first.first);
    if (counterpart.second < 0) {
      counterpart.second *= -1;
    } else {
      counterpart.first *= -1;
    }

    cerr << "(" << m.first.first << ", " << m.first.second << ", " << m.second
         << "), (" << counterpart.first << ", " << counterpart.second << ")"
         << endl;

    long long n_counterpart = M[counterpart];
    M[counterpart] = 0;
    if (n_counterpart != 0) {
      ans *= ((modpow(2, n) + modpow(2, n_counterpart)) % MOD - 1 + MOD) % MOD;
      ans %= MOD;
    } else {
      ans *= modpow(2, n);
      ans %= MOD;
    }
  }

  cout << (ans + zero_zero - 1 + MOD) % MOD << endl;
  return 0;
}