#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <iterator>
#include <numeric>
#include <cstdint>
#include <cmath>
#include <bitset>
#include <string>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>

#define N_TIMES(i, n)     for ( uint64_t i = 0;     i <  n; ++i )
#define N_TIMES_REV(i, n) for (  int64_t i = n - 1; i >= 0; --i )

using namespace std;

const uint64_t MOD = 1e+9 + 7;

uint64_t bin_pow(uint64_t x, uint64_t y)
{
  if (y <= 1) {
    return (y == 0) ? 1 : (x % MOD);
  }

  uint64_t w = bin_pow(x, y >> 1);
  uint64_t z = (w * w) % MOD;

  if (y % 2 == 1) {
    z = (x * z) % MOD;
  }

  return z;
}

uint64_t gcd(int64_t a, int64_t b)
{
  uint64_t n = min(a, b), m = max(a, b);
  return (n == 0) ? m : gcd(m % n, n);
}

struct Rational
{
  int64_t p, q;

  Rational(int64_t p = 0, int64_t q = 0) : p(p), q(q) {
    if (this->q < 0) {
      this->p *= -1;
      this->q *= -1;
    } else if (this->q == 0 && this->p < 0) {
      this->p *= -1;
      this->q *= -1;
    }
    
    int64_t t = gcd(abs(this->p), abs(this->q));
    this->p /= t;
    this->q /= t;
  }

  bool operator==(const Rational &rhs) const {
    return (p == rhs.p) && (q == rhs.q);
  }

  bool operator<(const Rational &rhs) const {
    return (p == rhs.p) ? (q < rhs.q) : (p < rhs.p);
  }
};

template<typename T, T MOD = 1e+9 + 7>
struct m_uint64_t_base
{
private:
  T _val;

public:
  m_uint64_t_base(T val = 0) : _val(val % MOD) {}

  T get() const { return _val; }
  
  m_uint64_t_base<T, MOD> pow(const T &e) const
  {
    if (e <= 1) {
      return (e == 0) ? m_uint64_t_base<T, MOD>(1) : (*this);
    }

    m_uint64_t_base<T, MOD> w = pow(e >> 1);
    m_uint64_t_base<T, MOD> z = w * w;

    if (e % 2 == 1) { z *= (*this); }

    return z;
  }

  m_uint64_t_base<T, MOD> inv() const { return pow(MOD - 2); }

  bool operator==(const T &rhs) const { return _val == (rhs % MOD); }
  bool operator!=(const T &rhs) const { return _val != (rhs % MOD); }
  bool operator< (const T &rhs) const { return _val <  (rhs % MOD); }
  bool operator<=(const T &rhs) const { return _val <= (rhs % MOD); }
  bool operator> (const T &rhs) const { return _val >  (rhs % MOD); }
  bool operator>=(const T &rhs) const { return _val >= (rhs % MOD); }

  bool operator==(const m_uint64_t_base<T, MOD> &rhs) const { return _val == rhs.get(); }
  bool operator!=(const m_uint64_t_base<T, MOD> &rhs) const { return _val != rhs.get(); }
  bool operator< (const m_uint64_t_base<T, MOD> &rhs) const { return _val <  rhs.get(); }
  bool operator<=(const m_uint64_t_base<T, MOD> &rhs) const { return _val <= rhs.get(); }
  bool operator> (const m_uint64_t_base<T, MOD> &rhs) const { return _val >  rhs.get(); }
  bool operator>=(const m_uint64_t_base<T, MOD> &rhs) const { return _val >= rhs.get(); }

  m_uint64_t_base<T, MOD> operator+(const T &rhs) const {
    return m_uint64_t_base<T, MOD>((_val + (rhs % MOD)) % MOD);
  }
  m_uint64_t_base<T, MOD> operator-(const T &rhs) const {
    return m_uint64_t_base<T, MOD>((_val + (MOD - (rhs % MOD))) % MOD);
  }
  m_uint64_t_base<T, MOD> operator*(const T &rhs) const {
    return m_uint64_t_base<T, MOD>((_val * (rhs % MOD)) % MOD);
  }
  m_uint64_t_base<T, MOD> operator/(const T &rhs) const {
    return m_uint64_t_base<T, MOD>((_val * m_uint64_t_base<T, MOD>(rhs).inv().get()) % MOD);
  }
  m_uint64_t_base<T, MOD> operator+(const m_uint64_t_base<T, MOD> &rhs) const {
    return m_uint64_t_base<T, MOD>((_val + rhs.get()) % MOD);
  }
  m_uint64_t_base<T, MOD> operator-(const m_uint64_t_base<T, MOD> &rhs) const {
    return m_uint64_t_base<T, MOD>((_val + (MOD - rhs.get())) % MOD);
  }
  m_uint64_t_base<T, MOD> operator*(const m_uint64_t_base<T, MOD> &rhs) const {
    return m_uint64_t_base<T, MOD>((_val * rhs.get()) % MOD);
  }
  m_uint64_t_base<T, MOD> operator/(const m_uint64_t_base<T, MOD> &rhs) const {
    return m_uint64_t_base<T, MOD>((_val * rhs.inv().get()) % MOD);
  }

  m_uint64_t_base<T, MOD>& operator+=(const T &rhs) {
    _val = (_val + (rhs % MOD)) % MOD;
    return *this;
  }
  m_uint64_t_base<T, MOD>& operator-=(const T &rhs) {
    _val = (_val + (MOD - (rhs % MOD))) % MOD;
    return *this;
  }
  m_uint64_t_base<T, MOD>& operator*=(const T &rhs) {
    _val = (_val * (rhs % MOD)) % MOD;
    return *this;
  }
  m_uint64_t_base<T, MOD>& operator/=(const T &rhs) {
    _val = (_val * m_uint64_t_base<T, MOD>(rhs).inv().get()) % MOD;
    return *this;
  }
  m_uint64_t_base<T, MOD>& operator+=(const m_uint64_t_base<T, MOD> &rhs) {
    _val = (_val + rhs.get()) % MOD;
    return *this;
  }
  m_uint64_t_base<T, MOD>& operator-=(const m_uint64_t_base<T, MOD> &rhs) {
    _val = (_val + (MOD - rhs.get())) % MOD;
    return *this;
  }
  m_uint64_t_base<T, MOD>& operator*=(const m_uint64_t_base<T, MOD> &rhs) {
    _val = (_val * rhs.get()) % MOD;
    return *this;
  }
  m_uint64_t_base<T, MOD>& operator/=(const m_uint64_t_base<T, MOD> &rhs) {
    _val = (_val * rhs.inv().get()) % MOD;
    return *this;
  }
};

typedef m_uint64_t_base<uint64_t, MOD> m_uint64_t;

istream& operator>>(istream& is, m_uint64_t &v)
{
  uint64_t u;
  is >> u;
  v = m_uint64_t(u);
  return is;
}

ostream& operator<<(ostream& os, const m_uint64_t &v)
{
  os << v.get();
  return os;
}

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

  uint64_t count_zero_vec = 0;
  multiset<Rational> P;
  N_TIMES(n, N) {
    int64_t A, B;
    cin >> A >> B;

    if (A == 0 && B == 0) {
      ++count_zero_vec;
    } else {
      P.emplace(A, B);
    }
  }

  map<Rational, pair<uint64_t, uint64_t>> counter;
  for (const Rational &p : P) {
    Rational q(-p.q, p.p);
    bool not_find_p = counter.find(p) == counter.end();
    bool not_find_q = counter.find(q) == counter.end();

    if (not_find_p && not_find_q) {
      counter.emplace(p, make_pair(P.count(p), P.count(q)));
    }
  }

  m_uint64_t S = 1;
  for (auto tuple : counter) {
    auto calc_pow2_sub1 = [&](uint64_t x) { return m_uint64_t(2).pow(x) - 1; };
    m_uint64_t T = 0;

    T += calc_pow2_sub1(tuple.second.first);
    T += calc_pow2_sub1(tuple.second.second);
    T += 1;

    S *= T;
  }
  S += count_zero_vec;
  S -= 1;
  cout << S << endl;

  return 0;
}

Measured memory_bytes: 31592