#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
const ll MOD = 1e9 + 7;
template <ll MOD>
struct ModInt {
  ll value;
  ModInt() : value(0) {}
  ModInt(const ll& v) : value(v % MOD) {
    if (value < 0) value += MOD;
  }
  ModInt<MOD>& operator=(const ModInt& o) {
    value = o.value;
    return *this;
  }
  inline bool operator==(const ModInt& o) { return value == o.value; }
  inline bool operator!=(const ModInt& o) { return value != o.value; }
  ModInt<MOD>& operator+=(const ModInt& o) {
    value += o.value;
    if (value >= MOD) value -= MOD;
    return *this;
  }
  ModInt<MOD>& operator-=(const ModInt& o) {
    value += MOD - o.value;
    if (value >= MOD) value -= MOD;
    return *this;
  }
  ModInt<MOD>& operator*=(const ModInt& o) {
    value *= o.value;
    value %= MOD;
    return *this;
  }
  ModInt<MOD>& operator/=(const ModInt& o) {
    value *= inverse(o.value);
    value %= MOD;
    return *this;
  }
  ModInt<MOD> operator-() { return ModInt<MOD>(-value); }
  ModInt<MOD> operator+(const ModInt& o) {
    ModInt<MOD> r(*this);
    r += o;
    return r;
  }
  ModInt<MOD> operator-(const ModInt& o) {
    ModInt<MOD> r(*this);
    r -= o;
    return r;
  }
  ModInt<MOD> operator*(const ModInt& o) {
    ModInt<MOD> r(*this);
    r *= o;
    return r;
  }
  ModInt<MOD> operator/(const ModInt& o) {
    ModInt<MOD> r(*this);
    r /= o;
    return r;
  }
  ModInt<MOD> pow(ll n) {
    ModInt<MOD> t(*this), r = 1;
    while (n > 0) {
      if (n & 1) r *= t;
      t *= t;
      n >>= 1;
    }
    return r;
  }

 private:
  ll inverse(ll a) {
    ModInt<MOD> t(a);
    return t.pow(MOD - 2).value;
  }
};
template <ll MOD>
std::ostream& operator<<(std::ostream& os, const ModInt<MOD>& o) {
  os << o.value;
  return os;
}
template <ll MOD>
std::istream& operator>>(std::istream& is, ModInt<MOD>& o) {
  is >> o.value;
  return is;
}
template <typename T>
struct Combination {
  ll n_max;
  vector<T> fac, finv, inv;
  Combination(ll n_max) {
    fac.resize(n_max + 1);
    finv.resize(n_max + 1);
    inv.resize(n_max + 1);
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[0] = 0, inv[1] = 1;
    for (int i = 2; i <= n_max; i++) {
      fac[i] = fac[i - 1] * i;
      inv[i] = -inv[MOD % i] * (MOD / i);
      finv[i] = finv[i - 1] * inv[i];
    }
  }
  T C(ll n, ll k) {
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k];
  }
  T P(ll n, ll k) {
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[n - k];
  }
  T H(ll n, ll k) { return C(n + k - 1, k); }
};
using Int = ModInt<MOD>;
ll solve() {
  ll N, a, b;
  cin >> N;
  map<pii, ll> cs;
  auto gcd = [](ll a, ll b) {
    while (b != 0) {
      ll t = b;
      b = a % b;
      a = t;
    }
    return a;
  };
  for (int i = 0; i < N; i++) {
    cin >> a >> b;
    if (a == 0 && b == 0) {
    } else if (a == 0) {
      b = 1;
    } else if (b == 0) {
      a = 1;
    } else {
      bool nega = false;
      if (b < 0) {
        a = -a;
        b = -b;
        if (a < 0) {
          nega = true;
          a = -a;
        }
      }
      ll g = gcd(a, b);
      a /= g;
      b /= g;
      if (nega) a = -a;
    }
    cs[pii(a, b)]++;
  }
  Int ans(1);
  set<pii> checked;
  for (auto c : cs) {
    a = c.first.first;
    b = c.first.second;
    if (a == 0 && b == 0) continue;
    if (checked.count(c.first) > 0) continue;
    pii v;
    if (a <= 0)
      v = pii(b, -a);
    else
      v = pii(-b, a);
    Int t(0);
    t += Int(2).pow(c.second) - Int(1);
    if (cs.count(v) > 0) {
      t += Int(2).pow(cs[v]) - Int(1);
    }
    t += 1;
    ans *= t;
    checked.insert(c.first);
    checked.insert(v);
  }
  if (cs.count(pii(0, 0)) > 0) {
    ans += cs[pii(0, 0)];
  }
  ans -= 1;
  return ans.value;
}
int main() {
  auto ans = solve();
  cout << ans << "\n";
  return 0;
}
