#include <bits/stdc++.h>
using namespace std;
const long long 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) { 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;
  }
  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) {
  long long abZeroCnt = 0;
  unordered_map<pair<long long, long long>, long long, hash_pair> cnt;
  for (long long i = (0); i < (N); i++) {
    if (A[i] == 0 && B[i] == 0) {
      abZeroCnt++;
    } else if (A[i] == 0) {
      cnt[{1, 0}]++;
    } else if (B[i] == 0) {
      cnt[{-1, 0}]++;
    } else {
      long long a = A[i], b = B[i];
      long long 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) {
    long long a = el.first.first, b = el.first.second;
    mod::mint<MOD> current = mod::pow(2, el.second, MOD);
    auto counterpart = a > 0 ? pair<long long, long long>{-b, a}
                             : pair<long long, long long>{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() {
  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;
}
