#include <bits/stdc++.h>
const int MAXN = 2e5 + 5;
const int MOD = 1e9 + 7;
int size[MAXN][2]{};
int two[MAXN];
long long A, B;
int K, N;
int ret;
template <typename T>
T gcd(T a, T b) {
  return (b) ? gcd(b, a % b) : a;
}
struct Frac {
  long long A, B;
  bool operator<(const Frac& o) const { return (A * o.B) < (o.A * B); }
  void reduce() {
    long long G = gcd(A, B);
    A /= G;
    B /= G;
    return this->sign();
  }
  void sign() {
    if (B > 0) return;
    if ((A >= 0) && (B >= 0)) return;
    A *= -1;
    B *= -1;
  }
  void display() const { printf("%lld / %lld\n", A, B); }
};
std::map<Frac, int> C;
Frac f;
void compute(int i) {
  if (!f.A && !f.B) return;
  f.reduce();
  if (C.count(f)) {
    ++size[C.at(f)][0];
    return;
  }
  Frac g = {-f.B, f.A};
  g.sign();
  if (C.count(g)) {
    ++size[C.at(g)][1];
    return;
  }
  C[f] = K++;
  ++size[C.at(f)][0];
}
void init() {
  two[0] = 1;
  for (int i = 1; i <= N; ++i) {
    two[i] = 2LL * two[i - 1] % MOD;
  }
}
int main() {
  scanf("%d", &N);
  init();
  for (int i = 1; i <= N; ++i) {
    scanf(" %lld%lld", &f.A, &f.B);
    compute(i);
  }
  ret = 1;
  for (int i = 0; i < K; ++i) {
    int cnt = (1LL * two[size[i][0]] + two[size[i][1]] - 1 + MOD) % MOD;
    ret = 1LL * ret * cnt % MOD;
  }
  ret = (1LL * ret - 1 + MOD) % MOD;
  printf("%d\n", ret);
  return 0;
}
