Problem p02679 (C++) — buggy submission, verdict: Runtime Error

#ifdef LOCAL
#include <header.hpp>
#else
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#endif
#define lp(i, l, r) for (auto i = regu(l); i <= decltype(i)(r); ++i)
#define rp(i, r, l) for (auto i = regu(r); i >= decltype(i)(l); --i)
#define lv(i, a) for (int i = 0; i < int(a.size()); ++i)
#define rv(i, a) for (int i = int(a.size()) - 1; i >= 0; --i)
#define lm(i, m) for (auto i = m; i; i = (m) & (i - 1))
#define many for (int C = 1, T = -1; T < 0 && cin >> T, C <= T; ++C)
#define goog "Case #" + to_string(C) + ":"
#define rang(a) begin(a), end(a)
#define elif else if
#ifndef LOCAL
#define endl '\\n'
#undef assert
#define assert
#endif
using namespace std;
using namespace __gnu_pbds;
const auto eps = 1e-8, pi = M_PI;
int comp(const double &a, const double &b) {
  return a < b - eps ? -1 : (a > b + eps);
}
#if __cplusplus > 201103L
template <class T> auto regu(const T &a) { return int(a); }
template <> auto regu(const int64_t &a) { return a; }
template <> auto regu(const uint64_t &a) { return int64_t(a); }
#else
template <class T> int64_t regu(const T &a) { return a; }
template <> int64_t regu(const uint32_t &a) { return int(a); }
#endif
template <class T> int barr(const T &a, const int &i) { return a >> i & 1; }
template <class T> int bcnt(const T &a) { return __builtin_popcount(a); }
template <> int bcnt(const int64_t &a) { return __builtin_popcountll(a); }
template <class T> int blen(const T &a) { return a ? 1 + blen(a / 2) : 0; }
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
template <class T> T rint(T l, T r) {
  return uniform_int_distribution<T>(l, r)(rng);
}
template <class A, class B> B conv(const A &a, B b = B()) {
  stringstream s;
  s << a, s >> b;
  return b;
}
template <class T = int> T inf() { return numeric_limits<T>::max() / 2; }
template <class T> T sign(const T &a) { return a == 0 ? 0 : (a < 0 ? -1 : 1); }
template <class T> T floor(const T &a, const T &b) {
  assert(b != 0);
  return sign(a) * sign(b) > 0 ? abs(a) / abs(b)
                               : -(abs(a) + abs(b) - 1) / abs(b);
}
template <class T> T ceil(const T &a, const T &b) {
  assert(b != 0);
  return sign(a) * sign(b) > 0 ? (abs(a) + abs(b) - 1) / abs(b)
                               : -abs(a) / abs(b);
}
template <class T> bool tmin(T &a, T b) { return b < a ? a = b, true : false; }
template <class T> bool tmax(T &a, T b) { return b > a ? a = b, true : false; }
#if __cplusplus > 201103L
template <class T> auto min(const T &a) { return *min_element(rang(a)); }
template <class T> auto max(const T &a) { return *max_element(rang(a)); }
template <class T> auto sum(const T &a) {
  return accumulate(rang(a), (typename T::value_type)0);
}
template <> auto sum(const vector<int> &a) { return accumulate(rang(a), 0ll); }
template <> auto sum(const vector<string> &a) {
  return accumulate(rang(a), string());
}
template <class C, class V> auto find(C &c, const V &v) {
  return find(rang(c), v);
}
template <class C, class V> auto find(const C &c, const V &v) {
  return find(rang(c), v);
}
#endif
template <class T, class C = less<typename T::value_type>>
void sort(T &a, C c = C()) {
  sort(rang(a), c);
}
template <class T> void reve(T &a) { reverse(rang(a)); }
template <class T> void shuf(T &a) { shuffle(rang(a), rng); }
template <class T> void merg(T l, T m, T r) { inplace_merge(l, m, r); }
#if __cplusplus > 201103L
template <class T> auto vect(const vector<T> &v, int n) {
  assert(v.size() <= 1);
  return v.size() ? vector<T>(n, v[0]) : vector<T>(n);
}
template <class T, class... D> auto vect(const vector<T> &v, int n, D... m) {
  return vector<decltype(vect(v, m...))>(n, vect(v, m...));
}
#endif
template <class T> double x(const complex<T> &a) { return a.real(); }
template <class T> double y(const complex<T> &a) { return a.imag(); }
template <class T> complex<T> rota(const complex<T> &p, const T &t) {
  return p * complex<T>(polar(1., -t));
}
template <class T>
complex<T> rota(const complex<T> &p, const complex<T> &a, const T &t) {
  return (p - a) * complex<T>(polar(1., -t)) + a;
}
template <class T>
complex<T> squa_dist(const complex<T> &a, const complex<T> &b) {
  return norm(a - b);
}
template <class T> T dist(const complex<T> &a, const complex<T> &b) {
  return abs(a - b);
}
template <class T> T dot(const complex<T> &a, const complex<T> &b) {
  return x(conj(a) * b);
}
template <class T> T cros(const complex<T> &a, const complex<T> &b) {
  return y(conj(a) * b);
}
template <class T>
T angl(const complex<T> &a, const complex<T> &b, const complex<T> &c) {
  return abs(remainder(arg(a - b) - arg(c - b), 2 * pi));
}
template <class T>
complex<T> inte(const complex<T> &a, const complex<T> &b, const complex<T> &c,
                const complex<T> &d) {
  T u = cros(c - a, b - a), v = cros(d - a, b - a);
  return (u * d - v * c) / (u - v);
}
template <class T> complex<T> proj(const complex<T> &p, const complex<T> &a) {
  return a * dot(p, a) / norm(a);
}
template <class T>
complex<T> proj(const complex<T> &p, const complex<T> &a, const complex<T> &b) {
  return a + (b - a) * dot(p - a, b - a) / norm(b - a);
}
template <class T>
complex<T> refl(const complex<T> &p, const complex<T> &a, const complex<T> &b) {
  return a + conj((p - a) / (b - a)) * (b - a);
}
template <class T> int comp(const complex<T> &a, const complex<T> &b) {
  int t = comp(x(a), x(b));
  if (t)
    return t;
  return comp(y(a), y(b));
}
namespace std {
template <>
bool operator==(const complex<double> &a, const complex<double> &b) {
  return !comp(x(a), x(b));
}
template <>
bool operator!=(const complex<double> &a, const complex<double> &b) {
  return comp(x(a), x(b));
}
} // namespace std
template <class T> struct less<complex<T>> {
  bool operator()(const complex<T> &a, const complex<T> &b) const {
    return comp(a, b) < 0;
  }
};
template <class T> istream &operator>>(istream &s, complex<T> &a) {
  T x, y;
  return s >> x >> y, a.real(x), a.imag(y), s;
}
template <class T> ostream &operator<<(ostream &s, const complex<T> &a) {
  return s << x(a) << " " << y(a);
}
template <class F, class S> istream &operator>>(istream &s, pair<F, S> &a) {
  return s >> a.first >> a.second;
}
template <class F, class S>
ostream &operator<<(ostream &s, const pair<F, S> &a) {
  return s << a.first << " " << a.second;
}
template <class T> istream &operator>>(istream &s, vector<T> &a) {
  for (int i = -1; i < 0 && (!a.size() && (cin >> i, a.resize(i), 0), i = 0),
           i < int(a.size());)
    s >> a[i++];
  return s;
}
template <class T> ostream &operator<<(ostream &s, const vector<T> &a) {
  lv(i, a) cout << a[i] << (i + 1 == int(a.size()) ? "" : " ");
  return s;
}
template <class T> T in() {
  T a;
  cin >> a;
  return a;
}
template <class T> void in(T &a) { cin >> a; }
template <class A, class... B> void in(A &a, B &...b) { cin >> a, in(b...); }
void ou() { cout << endl; }
template <class T> void ou(const T &a) { cout << a << endl; }
template <class A, class... B> void ou(const A &a, const B &...b) {
  cout << a << ' ', ou(b...);
}
void yep(const bool &a) { ou(a ? "yes" : "no"); }
void Yep(const bool &a) { ou(a ? "Yes" : "No"); }
void YEP(const bool &a) { ou(a ? "YES" : "NO"); }
template <class T> struct hash_safe {};
template <> struct hash_safe<int> {
  size_t operator()(uint64_t a) const {
    static uint64_t d = chrono::steady_clock::now().time_since_epoch().count();
    a += d + 0x9e3779b97f4a7c15, a = (a ^ (a >> 30)) * 0xbf58476d1ce4e5b9;
    a = (a ^ (a >> 27)) * 0x94d049bb133111eb;
    return a ^ (a >> 31);
  }
};
template <> struct hash_safe<int64_t> {
  size_t operator()(uint64_t a) const { return hash_safe<int>()(a); }
};
template <class A, class B> struct hash_safe<pair<A, B>> {
  size_t operator()(pair<A, B> a) const {
    auto h = hash_safe<A>()(a.first), g = hash_safe<B>()(a.second);
    return (h >> 16 << 16) + (g >> 16);
  }
};
template <class T> using unordered_set_safe = unordered_set<T, hash_safe<T>>;
template <class T>
using unordered_multiset_safe = unordered_multiset<T, hash_safe<T>>;
template <class K, class V>
using unordered_map_safe = unordered_map<K, V, hash_safe<K>>;
template <class K, class V>
using unordered_multimap_safe = unordered_multimap<K, V, hash_safe<K>>;
#define unordered_set unordered_set_safe
#define unordered_multiset unordered_multiset_safe
#define unordered_map unordered_map_safe
#define unordered_multimap unordered_multimap_safe
template <class T, class C = less<T>>
using bbst =
    tree<T, null_type, C, rb_tree_tag, tree_order_statistics_node_update>;
template <class T, class C = greater<T>>
using heap = __gnu_pbds::priority_queue<T, C, pairing_heap_tag>;
using ll = int64_t;
using str = string;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pt = complex<double>;
using vi = vector<int>;
using vl = vector<ll>;
using vai = valarray<int>;
using val = valarray<ll>;
using vpii = vector<pii>;
using vpll = vector<pll>;
using vvi = vector<vi>;
namespace modular_arithmetic {
#ifdef LOCAL
template <class T> T multiply(T x, T y, const T &z) {
  return T((long long)x * y % z);
}
template <>
long long multiply<long long>(long long a, long long b, const long long &c) {
  ll r = 0;
  for (; b; b & 1 ? r = (r + a) % c : 0, b >>= 1, a = (a + a) % c)
    ;
  return r;
}
#else
template <class T> T multiply(const T &x, const T &y, const T &z) {
  return T((long long)x * y % z);
}
template <>
long long multiply<long long>(const long long &x, const long long &y,
                              const long long &z) {
  return (x * y - (long long)(((long double)x * y + 0.5) / z) * z + z) % z;
}
#endif
template <class T = int, T M = 998244353> struct integer {
  integer() : v(0) {}
  integer(T t) : v(t) { wrap_around(); }
  integer(int64_t t) {
    if (t < 0)
      v = (t % M + M) % M;
    else if (t >= M)
      v = t % M;
  }
  void wrap_around() {
    if (v < 0)
      v = (v % M + M) % M;
    else if (v >= M)
      v %= M;
  }
  auto operator-() const {
    integer<T, M> a;
    a.v = (v ? M - v : 0);
    return a;
  }
  auto &operator+=(integer<T, M> a) { return *this = *this + a; }
  auto &operator-=(integer<T, M> a) { return *this = *this - a; }
  auto &operator*=(integer<T, M> a) { return *this = *this * a; }
  auto &operator/=(integer<T, M> a) { return *this = *this / a; }
  auto &operator<<=(T a) { return *this = *this << a; };
  auto &operator>>=(T a) { return *this = *this >> a; };
  friend auto operator/(integer<T, M> a, integer<T, M> b) {
    return a * inverse(b);
  }
  friend auto operator+(integer<T, M> a, integer<T, M> b) {
    integer<T, M> c;
    c.v = a.v + b.v;
    if (c.v >= M)
      c.v -= M;
    return c;
  }
  friend auto operator-(integer<T, M> a, integer<T, M> b) {
    integer<T, M> c;
    c.v = a.v - b.v;
    if (c.v < 0)
      c.v += M;
    return c;
  }
  friend auto operator*(integer<T, M> a, integer<T, M> b) {
    integer<T, M> c;
    c.v = multiply(a.v, b.v, M);
    return c;
  }
  friend auto operator^(integer<T, M> a, T b) { return pow(a, b); }
  friend bool operator==(integer<T, M> a, integer<T, M> b) {
    return a.v == b.v;
  }
  friend bool operator!=(integer<T, M> a, integer<T, M> b) {
    return a.v != b.v;
  }
  friend bool operator<(integer<T, M> a, integer<T, M> b) { return a.v < b.v; };
  friend bool operator<=(integer<T, M> a, integer<T, M> b) {
    return a.v <= b.v;
  };
  friend bool operator>(integer<T, M> a, integer<T, M> b) { return a.v > b.v; };
  friend bool operator>=(integer<T, M> a, integer<T, M> b) {
    return a.v >= b.v;
  };
  static auto factorial(T a) {
    assert(a >= 0);
    auto &t = factorial_cache;
    while (a >= int(t.size()))
      t.push_back(t.back() * T(t.size()));
    return t[a];
  }
  static auto binary_coefficient(T n, T k) {
    assert(n >= 0 && k >= 0);
    if (n < k)
      return integer<T, M>();
    return factorial(n) / factorial(k) / factorial(n - k);
  }
  static auto random() {
    return integer<T, M>(uniform_int_distribution<T>(0, M - 1)(generator));
  }
  T v;
  static mt19937_64 generator;
  static vector<integer<T, M>> inverse_cache, factorial_cache;
};
template <class T, T M>
mt19937_64 integer<T, M>::generator(
    chrono::steady_clock::now().time_since_epoch().count());
template <class T, T M>
vector<integer<T, M>> integer<T, M>::inverse_cache(2, T(1));
template <class T, T M>
vector<integer<T, M>> integer<T, M>::factorial_cache(1, T(1));
template <class T, T M> auto &operator>>(istream &s, integer<T, M> &a) {
  s >> a.v;
  a.wrap_around();
  return s;
}
template <class T, T M> auto &operator<<(ostream &s, integer<T, M> a) {
  return s << a.v;
}
template <class T, T M> auto pow(integer<T, M> a, T b) {
  integer<T, M> r(1);
  if (b < 0)
    a = 1 / a, b = -b;
  for (; b; b >>= 1, a = a * a)
    if (b & 1)
      r = r * a;
  return r;
}
template <class T, T M> integer<T, M> inverse(T a) {
  return inverse(integer<T, M>(a));
}
template <class T> T extended_euclidean_algorithm(T a, T b, T &x, T &y) {
  if (!b) {
    x = 1, y = 0;
    return a;
  } else {
    T d = extended_euclidean_algorithm(b, a % b, y, x);
    y -= a / b * x;
    return d;
  }
}
template <class T, T M> integer<T, M> inverse(integer<T, M> a) {
  assert(a.v);
  if (a.v < T(integer<T, M>::inverse_cache.size()))
    return integer<T, M>::inverse_cache[a.v];
  T t;
  extended_euclidean_algorithm(a.v, M, a.v, t);
  if (a.v < 0)
    a.v += M;
  return a;
}
template <class T, T M> auto inverse_cached(T a) {
  return inverse_cached(integer<T, M>(a));
}
template <class T, T M> auto inverse_cached(integer<T, M> a) {
  assert(a.v);
  auto &t = integer<T, M>::inverse_cache;
  while (int(t.size()) <= a.v) {
    t.push_back(integer<T, M>(-M / T(t.size())) * t[M % t.size()]);
  }
  return t[a.v];
}
template <class T, T M> auto operator<<(integer<T, M> a, T b) {
  return a * pow(integer<T, M>(2), b);
}
template <class T, T M> auto operator>>(integer<T, M> a, T b) {
  return a / pow(integer<T, M>(2), b);
}
// Not tested.
template <class T, T M> auto sqrt(integer<T, M> a) {
  vector<integer<T, M>> r;
  if (!a.v)
    r.push_back(decltype(r)(0));
  else if (pow(a, M - 1 >> 1).v == 1) {
    int s = M - 1, t = 0;
    integer<T, M> b = 1;
    for (; pow(b, M - 1 >> 1).v != M - 1; b = integer<T, M>::random())
      ;
    for (; s % 2 == 0; ++t, s /= 2)
      ;
    integer<T, M> x = pow(a, (s + 1) / 2), e = pow(a, s);
    for (int i = 1; i < t; ++i, e = x * x / a)
      if (pow(e, 1 << t - i - 1).v != 1)
        x = x * pow(b, (1 << i - 1) * s);
    r.push_back(x);
    r.push_back(-x);
  }
  return r;
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<T> &y, T x) {
  return lagrange_interpolation(y, integer<T, M>(x));
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<T> &y, integer<T, M> x) {
  vector<integer<T, M>> t;
  for (auto v : y)
    t.push_back(integer<T, M>(v));
  return lagrange_interpolation(t, x);
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<integer<T, M>> &y, T x) {
  return lagrange_interpolation(y, integer<T, M>(x));
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<integer<T, M>> &y,
                                     integer<T, M> x) {
  vector<integer<T, M>> f(1, 1), g(y.size(), x), h(y.size(), x);
  for (int i = 1; i < int(y.size()); ++i) {
    f.push_back(f.back() * inverse_cached<T, M>(i));
    g[i] = h[i] -= i, g[i] *= g[i - 1];
  }
  for (int i = int(y.size()) - 2; i >= 0; --i)
    h[i] *= h[i + 1];
  integer<T, M> r = 0;
  for (int i = 0; i < int(y.size()); ++i) {
    integer<T, M> t = f[i] * f[y.size() - 1 - i];
    if (i)
      t *= g[i - 1];
    if (i + 1 != int(y.size()))
      t *= h[i + 1];
    if (int(y.size() - i - 1) % 2)
      t = -t;
    r += t * y[i];
  }
  return r;
}
const int candidate = 1073741789;
} // namespace modular_arithmetic
// The templates end here.
pll f(pll a) {
  ll g = __gcd(abs(a.first), abs(a.second));
  if (g)
    a.first /= g, a.second /= g;
  if (a.first == 0) {
    if (a.second)
      a.second = 1;
  }
  elif (a.first < 0) {
    a.first *= -1;
    a.second *= -1;
  }
  return a;
}
int main() {
  ios::sync_with_stdio(!cin.tie(0));
  cout << setprecision(16) << fixed;
  int n;
  in(n);
  vpll a(n);
  in(a);
  map<pll, vpll> b;
  for (auto v : a)
    b[f(v)].push_back(v);
  using intm = modular_arithmetic::integer<int, int(1e9 + 7)>;
  intm ans = 1, ans2;
  set<pll> vis;
  for (auto tmp : b) {
    if (vis.count(tmp.first))
      continue;
    if (tmp.first == pll(0, 0)) {
      ans2 = (int)tmp.second.size();
    } else {
      auto d2 = tmp.first;
      swap(d2.first, d2.second);
      d2.second *= -1;
      d2 = f(d2);
      // ou(tmp.first, d2, ans);
      if (!b.count(d2)) {
        ans *= intm(1) << (int)tmp.second.size();
      } else {
        vis.insert(d2);
        ans *= (intm(1) << (int)tmp.second.size()) +
               (intm(1) << (int)b[d2].size()) - 1;
      }
    }
  }
  ou(ans + ans2 - 1);
  return 0;
}


Error: 0

Fixed submission:

#ifdef LOCAL
#include <header.hpp>
#else
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#endif
#define lp(i, l, r) for (auto i = regu(l); i <= decltype(i)(r); ++i)
#define rp(i, r, l) for (auto i = regu(r); i >= decltype(i)(l); --i)
#define lv(i, a) for (int i = 0; i < int(a.size()); ++i)
#define rv(i, a) for (int i = int(a.size()) - 1; i >= 0; --i)
#define lm(i, m) for (auto i = m; i; i = (m) & (i - 1))
#define many for (int C = 1, T = -1; T < 0 && cin >> T, C <= T; ++C)
#define goog "Case #" + to_string(C) + ":"
#define rang(a) begin(a), end(a)
#define elif else if
#ifndef LOCAL
#define endl '\\n'
#undef assert
#define assert
#endif
using namespace std;
using namespace __gnu_pbds;
const auto eps = 1e-8, pi = M_PI;
int comp(const double &a, const double &b) {
  return a < b - eps ? -1 : (a > b + eps);
}
#if __cplusplus > 201103L
template <class T> auto regu(const T &a) { return int(a); }
template <> auto regu(const int64_t &a) { return a; }
template <> auto regu(const uint64_t &a) { return int64_t(a); }
#else
template <class T> int64_t regu(const T &a) { return a; }
template <> int64_t regu(const uint32_t &a) { return int(a); }
#endif
template <class T> int barr(const T &a, const int &i) { return a >> i & 1; }
template <class T> int bcnt(const T &a) { return __builtin_popcount(a); }
template <> int bcnt(const int64_t &a) { return __builtin_popcountll(a); }
template <class T> int blen(const T &a) { return a ? 1 + blen(a / 2) : 0; }
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
template <class T> T rint(T l, T r) {
  return uniform_int_distribution<T>(l, r)(rng);
}
template <class A, class B> B conv(const A &a, B b = B()) {
  stringstream s;
  s << a, s >> b;
  return b;
}
template <class T = int> T inf() { return numeric_limits<T>::max() / 2; }
template <class T> T sign(const T &a) { return a == 0 ? 0 : (a < 0 ? -1 : 1); }
template <class T> T floor(const T &a, const T &b) {
  assert(b != 0);
  return sign(a) * sign(b) > 0 ? abs(a) / abs(b)
                               : -(abs(a) + abs(b) - 1) / abs(b);
}
template <class T> T ceil(const T &a, const T &b) {
  assert(b != 0);
  return sign(a) * sign(b) > 0 ? (abs(a) + abs(b) - 1) / abs(b)
                               : -abs(a) / abs(b);
}
template <class T> bool tmin(T &a, T b) { return b < a ? a = b, true : false; }
template <class T> bool tmax(T &a, T b) { return b > a ? a = b, true : false; }
#if __cplusplus > 201103L
template <class T> auto min(const T &a) { return *min_element(rang(a)); }
template <class T> auto max(const T &a) { return *max_element(rang(a)); }
template <class T> auto sum(const T &a) {
  return accumulate(rang(a), (typename T::value_type)0);
}
template <> auto sum(const vector<int> &a) { return accumulate(rang(a), 0ll); }
template <> auto sum(const vector<string> &a) {
  return accumulate(rang(a), string());
}
template <class C, class V> auto find(C &c, const V &v) {
  return find(rang(c), v);
}
template <class C, class V> auto find(const C &c, const V &v) {
  return find(rang(c), v);
}
#endif
template <class T, class C = less<typename T::value_type>>
void sort(T &a, C c = C()) {
  sort(rang(a), c);
}
template <class T> void reve(T &a) { reverse(rang(a)); }
template <class T> void shuf(T &a) { shuffle(rang(a), rng); }
template <class T> void merg(T l, T m, T r) { inplace_merge(l, m, r); }
#if __cplusplus > 201103L
template <class T> auto vect(const vector<T> &v, int n) {
  assert(v.size() <= 1);
  return v.size() ? vector<T>(n, v[0]) : vector<T>(n);
}
template <class T, class... D> auto vect(const vector<T> &v, int n, D... m) {
  return vector<decltype(vect(v, m...))>(n, vect(v, m...));
}
#endif
template <class T> double x(const complex<T> &a) { return a.real(); }
template <class T> double y(const complex<T> &a) { return a.imag(); }
template <class T> complex<T> rota(const complex<T> &p, const T &t) {
  return p * complex<T>(polar(1., -t));
}
template <class T>
complex<T> rota(const complex<T> &p, const complex<T> &a, const T &t) {
  return (p - a) * complex<T>(polar(1., -t)) + a;
}
template <class T>
complex<T> squa_dist(const complex<T> &a, const complex<T> &b) {
  return norm(a - b);
}
template <class T> T dist(const complex<T> &a, const complex<T> &b) {
  return abs(a - b);
}
template <class T> T dot(const complex<T> &a, const complex<T> &b) {
  return x(conj(a) * b);
}
template <class T> T cros(const complex<T> &a, const complex<T> &b) {
  return y(conj(a) * b);
}
template <class T>
T angl(const complex<T> &a, const complex<T> &b, const complex<T> &c) {
  return abs(remainder(arg(a - b) - arg(c - b), 2 * pi));
}
template <class T>
complex<T> inte(const complex<T> &a, const complex<T> &b, const complex<T> &c,
                const complex<T> &d) {
  T u = cros(c - a, b - a), v = cros(d - a, b - a);
  return (u * d - v * c) / (u - v);
}
template <class T> complex<T> proj(const complex<T> &p, const complex<T> &a) {
  return a * dot(p, a) / norm(a);
}
template <class T>
complex<T> proj(const complex<T> &p, const complex<T> &a, const complex<T> &b) {
  return a + (b - a) * dot(p - a, b - a) / norm(b - a);
}
template <class T>
complex<T> refl(const complex<T> &p, const complex<T> &a, const complex<T> &b) {
  return a + conj((p - a) / (b - a)) * (b - a);
}
template <class T> int comp(const complex<T> &a, const complex<T> &b) {
  int t = comp(x(a), x(b));
  if (t)
    return t;
  return comp(y(a), y(b));
}
namespace std {
template <>
bool operator==(const complex<double> &a, const complex<double> &b) {
  return !comp(x(a), x(b));
}
template <>
bool operator!=(const complex<double> &a, const complex<double> &b) {
  return comp(x(a), x(b));
}
} // namespace std
template <class T> struct less<complex<T>> {
  bool operator()(const complex<T> &a, const complex<T> &b) const {
    return comp(a, b) < 0;
  }
};
template <class T> istream &operator>>(istream &s, complex<T> &a) {
  T x, y;
  return s >> x >> y, a.real(x), a.imag(y), s;
}
template <class T> ostream &operator<<(ostream &s, const complex<T> &a) {
  return s << x(a) << " " << y(a);
}
template <class F, class S> istream &operator>>(istream &s, pair<F, S> &a) {
  return s >> a.first >> a.second;
}
template <class F, class S>
ostream &operator<<(ostream &s, const pair<F, S> &a) {
  return s << a.first << " " << a.second;
}
template <class T> istream &operator>>(istream &s, vector<T> &a) {
  for (int i = -1; i < 0 && (!a.size() && (cin >> i, a.resize(i), 0), i = 0),
           i < int(a.size());)
    s >> a[i++];
  return s;
}
template <class T> ostream &operator<<(ostream &s, const vector<T> &a) {
  lv(i, a) cout << a[i] << (i + 1 == int(a.size()) ? "" : " ");
  return s;
}
template <class T> T in() {
  T a;
  cin >> a;
  return a;
}
template <class T> void in(T &a) { cin >> a; }
template <class A, class... B> void in(A &a, B &...b) { cin >> a, in(b...); }
void ou() { cout << endl; }
template <class T> void ou(const T &a) { cout << a << endl; }
template <class A, class... B> void ou(const A &a, const B &...b) {
  cout << a << ' ', ou(b...);
}
void yep(const bool &a) { ou(a ? "yes" : "no"); }
void Yep(const bool &a) { ou(a ? "Yes" : "No"); }
void YEP(const bool &a) { ou(a ? "YES" : "NO"); }
template <class T> struct hash_safe {};
template <> struct hash_safe<int> {
  size_t operator()(uint64_t a) const {
    static uint64_t d = chrono::steady_clock::now().time_since_epoch().count();
    a += d + 0x9e3779b97f4a7c15, a = (a ^ (a >> 30)) * 0xbf58476d1ce4e5b9;
    a = (a ^ (a >> 27)) * 0x94d049bb133111eb;
    return a ^ (a >> 31);
  }
};
template <> struct hash_safe<int64_t> {
  size_t operator()(uint64_t a) const { return hash_safe<int>()(a); }
};
template <class A, class B> struct hash_safe<pair<A, B>> {
  size_t operator()(pair<A, B> a) const {
    auto h = hash_safe<A>()(a.first), g = hash_safe<B>()(a.second);
    return (h >> 16 << 16) + (g >> 16);
  }
};
template <class T> using unordered_set_safe = unordered_set<T, hash_safe<T>>;
template <class T>
using unordered_multiset_safe = unordered_multiset<T, hash_safe<T>>;
template <class K, class V>
using unordered_map_safe = unordered_map<K, V, hash_safe<K>>;
template <class K, class V>
using unordered_multimap_safe = unordered_multimap<K, V, hash_safe<K>>;
#define unordered_set unordered_set_safe
#define unordered_multiset unordered_multiset_safe
#define unordered_map unordered_map_safe
#define unordered_multimap unordered_multimap_safe
template <class T, class C = less<T>>
using bbst =
    tree<T, null_type, C, rb_tree_tag, tree_order_statistics_node_update>;
template <class T, class C = greater<T>>
using heap = __gnu_pbds::priority_queue<T, C, pairing_heap_tag>;
using ll = int64_t;
using str = string;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pt = complex<double>;
using vi = vector<int>;
using vl = vector<ll>;
using vai = valarray<int>;
using val = valarray<ll>;
using vpii = vector<pii>;
using vpll = vector<pll>;
using vvi = vector<vi>;
namespace modular_arithmetic {
#ifdef LOCAL
template <class T> T multiply(T x, T y, const T &z) {
  return T((long long)x * y % z);
}
template <>
long long multiply<long long>(long long a, long long b, const long long &c) {
  ll r = 0;
  for (; b; b & 1 ? r = (r + a) % c : 0, b >>= 1, a = (a + a) % c)
    ;
  return r;
}
#else
template <class T> T multiply(const T &x, const T &y, const T &z) {
  return T((long long)x * y % z);
}
template <>
long long multiply<long long>(const long long &x, const long long &y,
                              const long long &z) {
  return (x * y - (long long)(((long double)x * y + 0.5) / z) * z + z) % z;
}
#endif
template <class T = int, T M = 998244353> struct integer {
  integer() : v(0) {}
  integer(T t) : v(t) { wrap_around(); }
  integer(int64_t t) {
    if (t < 0)
      v = (t % M + M) % M;
    else if (t >= M)
      v = t % M;
  }
  void wrap_around() {
    if (v < 0)
      v = (v % M + M) % M;
    else if (v >= M)
      v %= M;
  }
  auto operator-() const {
    integer<T, M> a;
    a.v = (v ? M - v : 0);
    return a;
  }
  auto &operator+=(integer<T, M> a) { return *this = *this + a; }
  auto &operator-=(integer<T, M> a) { return *this = *this - a; }
  auto &operator*=(integer<T, M> a) { return *this = *this * a; }
  auto &operator/=(integer<T, M> a) { return *this = *this / a; }
  auto &operator<<=(T a) { return *this = *this << a; };
  auto &operator>>=(T a) { return *this = *this >> a; };
  friend auto operator/(integer<T, M> a, integer<T, M> b) {
    return a * inverse(b);
  }
  friend auto operator+(integer<T, M> a, integer<T, M> b) {
    integer<T, M> c;
    c.v = a.v + b.v;
    if (c.v >= M)
      c.v -= M;
    return c;
  }
  friend auto operator-(integer<T, M> a, integer<T, M> b) {
    integer<T, M> c;
    c.v = a.v - b.v;
    if (c.v < 0)
      c.v += M;
    return c;
  }
  friend auto operator*(integer<T, M> a, integer<T, M> b) {
    integer<T, M> c;
    c.v = multiply(a.v, b.v, M);
    return c;
  }
  friend auto operator^(integer<T, M> a, T b) { return pow(a, b); }
  friend bool operator==(integer<T, M> a, integer<T, M> b) {
    return a.v == b.v;
  }
  friend bool operator!=(integer<T, M> a, integer<T, M> b) {
    return a.v != b.v;
  }
  friend bool operator<(integer<T, M> a, integer<T, M> b) { return a.v < b.v; };
  friend bool operator<=(integer<T, M> a, integer<T, M> b) {
    return a.v <= b.v;
  };
  friend bool operator>(integer<T, M> a, integer<T, M> b) { return a.v > b.v; };
  friend bool operator>=(integer<T, M> a, integer<T, M> b) {
    return a.v >= b.v;
  };
  static auto factorial(T a) {
    assert(a >= 0);
    auto &t = factorial_cache;
    while (a >= int(t.size()))
      t.push_back(t.back() * T(t.size()));
    return t[a];
  }
  static auto binary_coefficient(T n, T k) {
    assert(n >= 0 && k >= 0);
    if (n < k)
      return integer<T, M>();
    return factorial(n) / factorial(k) / factorial(n - k);
  }
  static auto random() {
    return integer<T, M>(uniform_int_distribution<T>(0, M - 1)(generator));
  }
  T v;
  static mt19937_64 generator;
  static vector<integer<T, M>> inverse_cache, factorial_cache;
};
template <class T, T M>
mt19937_64 integer<T, M>::generator(
    chrono::steady_clock::now().time_since_epoch().count());
template <class T, T M>
vector<integer<T, M>> integer<T, M>::inverse_cache(2, T(1));
template <class T, T M>
vector<integer<T, M>> integer<T, M>::factorial_cache(1, T(1));
template <class T, T M> auto &operator>>(istream &s, integer<T, M> &a) {
  s >> a.v;
  a.wrap_around();
  return s;
}
template <class T, T M> auto &operator<<(ostream &s, integer<T, M> a) {
  return s << a.v;
}
template <class T, T M> auto pow(integer<T, M> a, T b) {
  integer<T, M> r(1);
  if (b < 0)
    a = 1 / a, b = -b;
  for (; b; b >>= 1, a = a * a)
    if (b & 1)
      r = r * a;
  return r;
}
template <class T, T M> integer<T, M> inverse(T a) {
  return inverse(integer<T, M>(a));
}
template <class T> T extended_euclidean_algorithm(T a, T b, T &x, T &y) {
  if (!b) {
    x = 1, y = 0;
    return a;
  } else {
    T d = extended_euclidean_algorithm(b, a % b, y, x);
    y -= a / b * x;
    return d;
  }
}
template <class T, T M> integer<T, M> inverse(integer<T, M> a) {
  assert(a.v);
  if (a.v < T(integer<T, M>::inverse_cache.size()))
    return integer<T, M>::inverse_cache[a.v];
  T t;
  extended_euclidean_algorithm(a.v, M, a.v, t);
  if (a.v < 0)
    a.v += M;
  return a;
}
template <class T, T M> auto inverse_cached(T a) {
  return inverse_cached(integer<T, M>(a));
}
template <class T, T M> auto inverse_cached(integer<T, M> a) {
  assert(a.v);
  auto &t = integer<T, M>::inverse_cache;
  while (int(t.size()) <= a.v) {
    t.push_back(integer<T, M>(-M / T(t.size())) * t[M % t.size()]);
  }
  return t[a.v];
}
template <class T, T M> auto operator<<(integer<T, M> a, T b) {
  return a * pow(integer<T, M>(2), b);
}
template <class T, T M> auto operator>>(integer<T, M> a, T b) {
  return a / pow(integer<T, M>(2), b);
}
// Not tested.
template <class T, T M> auto sqrt(integer<T, M> a) {
  vector<integer<T, M>> r;
  if (!a.v)
    r.push_back(decltype(r)(0));
  else if (pow(a, M - 1 >> 1).v == 1) {
    int s = M - 1, t = 0;
    integer<T, M> b = 1;
    for (; pow(b, M - 1 >> 1).v != M - 1; b = integer<T, M>::random())
      ;
    for (; s % 2 == 0; ++t, s /= 2)
      ;
    integer<T, M> x = pow(a, (s + 1) / 2), e = pow(a, s);
    for (int i = 1; i < t; ++i, e = x * x / a)
      if (pow(e, 1 << t - i - 1).v != 1)
        x = x * pow(b, (1 << i - 1) * s);
    r.push_back(x);
    r.push_back(-x);
  }
  return r;
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<T> &y, T x) {
  return lagrange_interpolation(y, integer<T, M>(x));
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<T> &y, integer<T, M> x) {
  vector<integer<T, M>> t;
  for (auto v : y)
    t.push_back(integer<T, M>(v));
  return lagrange_interpolation(t, x);
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<integer<T, M>> &y, T x) {
  return lagrange_interpolation(y, integer<T, M>(x));
}
template <class T, T M>
integer<T, M> lagrange_interpolation(const vector<integer<T, M>> &y,
                                     integer<T, M> x) {
  vector<integer<T, M>> f(1, 1), g(y.size(), x), h(y.size(), x);
  for (int i = 1; i < int(y.size()); ++i) {
    f.push_back(f.back() * inverse_cached<T, M>(i));
    g[i] = h[i] -= i, g[i] *= g[i - 1];
  }
  for (int i = int(y.size()) - 2; i >= 0; --i)
    h[i] *= h[i + 1];
  integer<T, M> r = 0;
  for (int i = 0; i < int(y.size()); ++i) {
    integer<T, M> t = f[i] * f[y.size() - 1 - i];
    if (i)
      t *= g[i - 1];
    if (i + 1 != int(y.size()))
      t *= h[i + 1];
    if (int(y.size() - i - 1) % 2)
      t = -t;
    r += t * y[i];
  }
  return r;
}
const int candidate = 1073741789;
} // namespace modular_arithmetic
// The templates end here.
pll f(pll a) {
  ll g = __gcd(abs(a.first), abs(a.second));
  a.first /= g, a.second /= g;
  if (a.first == 0) {
    if (a.second)
      a.second = 1;
  }
  elif (a.first < 0) {
    a.first *= -1;
    a.second *= -1;
  }
  return a;
}
int main() {
  ios::sync_with_stdio(!cin.tie(0));
  cout << setprecision(16) << fixed;
  int n;
  in(n);
  vpll a(n);
  in(a);
  map<pll, vpll> b;
  for (auto v : a)
    b[f(v)].push_back(v);
  using intm = modular_arithmetic::integer<int, int(1e9 + 7)>;
  intm ans = 1, ans2;
  set<pll> vis;
  for (auto tmp : b) {
    if (vis.count(tmp.first))
      continue;
    if (tmp.first == pll(0, 0)) {
      ans2 = (int)tmp.second.size() - 1;
    } else {
      auto d2 = tmp.first;
      swap(d2.first, d2.second);
      d2.second *= -1;
      d2 = f(d2);
      // ou(tmp.first, d2, ans);
      if (!b.count(d2)) {
        ans *= intm(1) << (int)tmp.second.size();
      } else {
        vis.insert(d2);
        ans *= (intm(1) << (int)tmp.second.size()) +
               (intm(1) << (int)b[d2].size()) - 1;
      }
    }
  }
  ou(ans + ans2 - 1);
  return 0;
}