#include <bits/stdc++.h>
using namespace std;
struct V {
  int64_t n;
  int64_t v;
};
struct N {
  int64_t np;
  int64_t nn;
};
int64_t gcd(int64_t a, int64_t b) {
  if (a < b) swap(a, b);
  if (a % b == 0) return b;
  return gcd(b, a % b);
}
int64_t powint(int64_t x, int64_t m) {
  if (m == 0) {
    return 1;
  }
  if (m == 1) {
    return x;
  }
  if (m & 1) {
    int64_t val = powint(x, m / 2);
    val = val * val;
    val *= x;
    return val;
  } else {
    int64_t val = powint(x, m / 2);
    val = val * val;
    return val;
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  auto cmp = [](const V& lhs, const V& rhs) {
    if (lhs.n != rhs.n) return lhs.n < rhs.n;
    return lhs.v < rhs.v;
  };
  map<V, N, decltype(cmp)> data(cmp);
  int64_t nzero = 0;
  for (int i = (int)(0); i < (int)(n); i++) {
    int64_t n, v;
    cin >> n >> v;
    if (n == 0 && v == 0) {
      nzero++;
      continue;
    }
    if (n == 0 || v == 0) {
      if (data.find({0, 0}) == data.end()) {
        data[{0, 0}] = {0, 0};
      }
      if (n == 0) {
        data[{0, 0}].np++;
      }
      if (v == 0) {
        data[{0, 0}].nn++;
      }
      continue;
    }
    bool is_p = (n < 0) == (v < 0);
    n = abs(n);
    v = abs(v);
    int64_t d = gcd(n, v);
    n /= d;
    v /= d;
    if (is_p) std::swap(n, v);
    if (data.find({n, v}) == data.end()) {
      data[{n, v}] = {0, 0};
    }
    if (is_p)
      data[{n, v}].nn++;
    else
      data[{n, v}].np++;
  }
  int64_t ans = 1;
  for (auto& n : data) {
    ans *= powint(2, n.second.nn) + powint(2, n.second.np) - 1;
  }
  ans += nzero - 1;
  cout << ans << endl;
  return 0;
}
