#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
template <class T>
void chmin(T& a, const T& b) noexcept {
  if (b < a) a = b;
}
template <class T>
void chmax(T& a, const T& b) noexcept {
  if (a < b) a = b;
}
void debug_out() { cout << "\n"; }
template <class T, class... Args>
void debug_out(const T& x, const Args&... args) {
  cout << x << " ";
  debug_out(args...);
}
const int mod = 1000000007;
struct mint {
  ll x;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod - a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1) a *= *this;
    return a;
  }
  mint inv() const { return pow(mod - 2); }
  mint& operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
  bool operator==(const mint rhs) const { return x == rhs.x; }
  bool operator!=(const mint rhs) const { return x != rhs.x; }
};
istream& operator>>(istream& is, mint& a) { return is >> a.x; }
ostream& operator<<(ostream& os, const mint& a) { return os << a.x; }
ll gcd_(ll x, ll y) { return y ? gcd_(y, x % y) : x; }
struct frac {
  ll nu, de;
  inline void normalize() {
    if (de < 0) {
      nu *= -1;
      de *= -1;
    }
    if (nu == 0 && de != 0)
      de = 1;
    else if (de == 0 && nu != 0)
      nu = 1;
    else {
      ll g = gcd_(llabs(nu), llabs(de));
      if (g == 0) {
        nu = 0;
        de = 1;
      } else {
        nu /= g;
        de /= g;
      }
    }
  }
  frac() : nu(0), de(1){};
  frac(ll a = 0, ll b = 1) : nu(a), de(b) { normalize(); };
  frac operator-() const { return frac(-nu, de); }
  frac& operator+=(const frac a) {
    nu = nu * a.de + a.nu * de;
    de *= a.de;
    normalize();
    return *this;
  }
  frac& operator-=(const frac a) {
    nu = nu * a.de - a.nu * de;
    de *= a.de;
    normalize();
    return *this;
  }
  frac& operator*=(const frac a) {
    nu *= a.nu;
    de *= a.de;
    normalize();
    return *this;
  }
  frac operator+(const frac a) const { return frac(*this) += a; }
  frac operator-(const frac a) const { return frac(*this) -= a; }
  frac operator*(const frac a) const { return frac(*this) *= a; }
  frac inv() const { return frac(de, nu); }
  frac& operator/=(const frac a) { return *this *= a.inv(); }
  frac operator/(const frac a) const { return frac(*this) /= a; }
  bool operator==(const frac rhs) const { return nu == rhs.nu && de == rhs.de; }
  bool operator!=(const frac rhs) const { return nu != rhs.nu || de != rhs.de; }
  bool operator<(const frac& a) const { return nu * a.de < a.nu * de; };
  bool operator>(const frac& a) const { return frac(*this) < a; };
  bool operator<=(const frac& a) const { return nu * a.de <= a.nu * de; };
  bool operator>=(const frac& a) const { return frac(*this) <= a; };
  long double to_d() const {
    long double d = nu / de;
    return d;
  }
};
ostream& operator<<(ostream& os, const frac& a) {
  return os << a.nu << "/" << a.de;
}
int main() {
  std::cin.tie(nullptr);
  std::ios_base::sync_with_stdio(false);
  std::cout << std::fixed << std::setprecision(15);
  int n;
  cin >> n;
  map<frac, int> mp;
  ll zero_zero = 0;
  ll a_zero = 0, zero_b = 0;
  for (int i = 0; i < (n); ++i) {
    ll a, b;
    cin >> a >> b;
    if (a == 0 && b == 0)
      zero_zero++;
    else if (a == 0)
      zero_b++;
    else if (b == 0)
      a_zero++;
    else
      mp[frac(a, b)]++;
  }
  set<frac> used;
  mint ans = mint(2).pow(zero_b) + mint(2).pow(a_zero) - 1;
  for (auto p : mp) {
    if (used.count(p.first)) continue;
    frac inv = -p.first.inv();
    mint now = 1;
    if (mp.count(inv)) {
      now += mint(2).pow(p.second) - 1;
      now += mint(2).pow(mp[inv]) - 1;
      ans *= now;
      used.insert(inv);
    } else
      ans *= mint(2).pow(p.second);
  }
  ans += zero_zero - 1;
  cout << ans << endl;
  return 0;
}
