#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#ifdef ENABLE_DEBUG
#define dump(a) cerr<<#a<<"="<<a<<endl
#define dumparr(a,n) cerr<<#a<<"["<<n<<"]="<<a[n]<<endl
#else
#define dump(a) 
#define dumparr(a,n) 
#endif
#define FOR(i, a, b) for(ll i = (ll)a;i < (ll)b;i++)
#define For(i, a) FOR(i, 0, a)
#define REV(i, a, b) for(ll i = (ll)b-1LL;i >= (ll)a;i--)
#define Rev(i, a) REV(i, 0, a)
#define REP(a) For(i, a)
#define SIGN(a) (a==0?0:(a>0?1:-1))

typedef long long int ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<ll, ll> pll;
typedef pair<ll,pll> ppll;
typedef vector<ll> vll;
typedef long double ld;
typedef pair<ld,ld> pdd;

const ll INF=(1LL<<60);
#if __cplusplus<201700L
ll gcd(ll a, ll b) {
  a=abs(a);
  b=abs(b);
  if(a==0)return b;
  if(b==0)return a;
  if(a < b) return gcd(b, a);
  ll r;
  while ((r=a%b)) {
    a = b;
    b = r;
  }
  return b;
}
#endif
template<class T>
bool chmax(T& a,const T& b){
  if(a<b){
    a=b;
    return true;
  }
  return false;
}
template<class T>
bool chmin(T& a,const T& b){
  if(a>b){
    a=b;
    return true;
  }
  return false;
}
template<class S,class T>
std::ostream& operator<<(std::ostream& os,pair<S,T> a){
  os << "(" << a.first << "," << a.second << ")";
  return os;
}
template<class T>
std::ostream& operator<<(std::ostream& os,vector<T> a){
  os << "[ ";
  REP(a.size()){
    os<< a[i] << " ";
  }
  os<< " ]";
  return os;
}
pll make_Q(ll a,ll b){
  pll ret;
  ll x,y;
    if(a==0){
      x=0;y=1;
    }else if(b==0){
      x=1;y=0;
    }else{
      ll tmp=gcd(a,b);
      x=a/tmp;
      y=b/tmp;
      if(x<0){
        x=-x;
        y=-y;
      }
    }
    ret.first=x;ret.second=y;
  return ret;
}
pll rev_Q(pll x){
  if(x.first==0&&x.second==0){
    return x;
  }
  if(x.first==0){
    return pll(1,0);
  }
  if(x.second==0){
    return pll(0,1);
  }
  pll ret;
  if(x.second<0){
    ret.first=-x.second;
    ret.second=x.first;
  }else{
    ret.first=x.second;
    ret.second=-x.first;
  }
  return ret;
}
const long long MOD = 1000000007;
template<typename T>
T modpow(T a,unsigned long long b){
  T base=a,ans=T(1LL);
  while(b){
    if(b&1){
      ans=ans*base%MOD;
    }
    base=base*base%MOD;
    b>>=1;
  }
  return ans;
}
void solve(long long N, std::vector<long long> A, std::vector<long long> B){
  map<pll,ll> cnt;
  map<pll,bool> flags;
  auto inc_m=[](const pll &x,map<pll,ll> &m){
    if(m.count(x)){
      ++m[x];
    }else{
      m[x]=1;
    }
  };
  ll zero=0;
  REP(N){
    dump(make_Q(A[i],B[i]));
    if(A[i]==0&&B[i]==0){++zero;continue;}
    inc_m(make_Q(A[i],B[i]),cnt);
    flags[make_Q(A[i],B[i])]=false;
  }
  ll ans=1;
  for (auto &&i : cnt)
  {
    if(flags[i.first])continue;
    flags[i.first]=flags[rev_Q(i.first)]=true;
    if(cnt.count(rev_Q(i.first))){
      ans=(ans*(modpow(2,i.second)+modpow(2,cnt[rev_Q(i.first)])-1)%MOD);
      dump(i.second);
      dump(cnt[rev_Q(i.first)]);
      dump(modpow(2,i.second)+modpow(2,cnt[rev_Q(i.first)]-1));
    }
    else ans=ans*modpow(2,i.second)%MOD;
  }
  cout<<ans-1+zero<<endl;
}

int main(){
  cout<<setprecision(1000);
    long long N;
    scanf("%lld",&N);
    std::vector<long long> A(N);
    std::vector<long long> B(N);
    for(int i = 0 ; i < N ; i++){
        scanf("%lld",&A[i]);
        scanf("%lld",&B[i]);
    }
    solve(N, std::move(A), std::move(B));
    return 0;
}
