#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define REP(i,n) for (ll i = 0; i < (n); ++i)
#define RREP(i, n) for (ll i = (n) - 1; i >= 0; --i)
#define ALL(v) (v).begin(), (v).end()


struct mint{
    static const long long MOD = 1000000007;

    long long v;

    mint() : v(0) {}
    mint(long long x){
        x = x % MOD;
        if(x < 0){ x += MOD; }
        v = x;
    }
    mint& operator+=(mint a){
        v += a.v;
        if(v >= MOD){ v -= MOD; }
        return *this;
    }
    mint& operator*=(mint a){
        v *= a.v;
        v %= MOD;
        return *this;
    }
    mint& operator-=(mint a){
        v -= a.v;
        if(v < 0){ v += MOD; }
        return *this;
    }
    mint& operator/=(mint a){
        return (*this) *= a.inv();
    }

    mint operator*(mint a) const{
        return mint(v) *= a;
    }

    mint operator+(mint a) const {
        return mint(v) += a;
    }

    mint operator-(mint a) const {
        return mint(v) -= a;
    }

    mint operator/(mint a) const {
        return mint(v) /= a;
    }

    mint pow(long long k) const {
        mint res(1),tmp(v);
        while(k){
            if(k&1) res *= tmp;
            tmp *= tmp;
            k >>= 1;
        }
        return res;
    }
    mint inv(){return pow(MOD - 2); }

    static mint comb(long long n, int k){
        mint res(1);
        for(int i = 0; i < k; ++i){
            res *= mint(n - i);
            res /= mint(i + 1);
        }
        return res;
    }

    static mint factorial(long long n){
        mint res(1);
        for(int i = n; i > 1; --i){
            res *= mint(i);
        }
        return res;
    }

    bool operator<(const mint &a) const {
        return v < a.v;
    };
};

mint operator*(long long l, mint r){ return r * l; }

std::ostream& operator<<(std::ostream& stream, const mint& m){
    stream << m.v;
    return stream;
}

ll gcd(ll a, ll b) {
    if(a < b){
        return gcd(b, a);
    }
    ll r;
    while ((r=a%b)) {
        a = b;
        b = r;
    }
    return b;
}

struct Frac{
    ll sign;
    ll a, b;
    Frac(ll sign, ll a, ll b) : sign(sign), a(a), b(b) {}
    Frac(ll a0, ll b0) {
        assert(a0 != 0 || b0 != 0);
        if(a0 != 0 && b0 != 0){
            const ll g = gcd(abs(a0), abs(b0));
            a0 /= g;
            b0 /= g;
            if((a0 > 0 && b0 > 0) || (a0 < 0 && b0 < 0)){
                sign = 1;
            }else{
                sign = -1;
            }
            a = abs(a0);
            b = abs(b0);
        }else if(a0 != 0){
            sign = 1;
            a = 1;
            b = 0;
        }else if(b0 != 0){
            sign = 1;
            a = 0;
            b = 1;
        }
    }

    const Frac flip() const {
        if(a != 0 && b != 0){
            return Frac(- sign, b, a);
        }else if(a == 0){
            return Frac(1, 1, 0);
        }else{
            assert(b == 0);
            return Frac(1, 0, 1);
        }
    }

    const Frac normalize() const {
        if(a == 0 || sign < 0){
            return flip();
        }else{
            return *this;
        }
    }

    bool operator==(const Frac& other) const {
        return sign == other.sign && a == other.a && b == other.b;
    }
    bool operator!=(const Frac& other) const { return !(*this == other); }
    bool operator<(const Frac& other) const {
        if(sign != other.sign){
            return sign < other.sign;
        }else if(a != other.a){
            return a < other.a;
        }else{
            return b < other.b;
        }
    }
};

int main(){
    ll n;
    cin >> n;

    mint num0 = 0;
    set<Frac> type;
    map<Frac, ll> count;
    REP(i, n){
        ll ai, bi;
        cin >> ai >> bi;
        if(ai == 0 && bi == 0){  // 全てのイワシと仲が悪い
            num0 += 1;
        }else{
            Frac f(ai, bi);
            assert(f.a >= 0 && f.b >= 0);
            count[f]++;
            if(f.normalize() != f){
                assert(f.normalize() == f.flip());
            }
            type.insert(f.normalize());
        }
    }

    vector<mint> pow2(n + 1);
    pow2.at(0) = 1;
    for(ll i = 1; i <= n; ++i){
        pow2.at(i) = pow2.at(i - 1) * 2;
    }

    mint ans = 1;
    for(const Frac& p : type){
        assert(p.flip().flip() == p);
        // cerr << "p=" << p.sign << " " << p.a << ", " << p.b << endl;
        // const auto q = p.flip();
        // cerr << "p.flip()=" << q.sign << " " << q.a << ", " << q.b << endl;
        const ll c1 = count[p];
        const ll c2 = count[p.flip()];
        mint tmp = 1;
        tmp += pow2.at(c1) - 1;
        tmp += pow2.at(c2) - 1;
        // cerr << "tmp=" << tmp << ", " << c1 << " " << c2 << endl;
        ans *= tmp;
    }
    cout << ans - 1 + num0 << endl;
    return 0;
}


Measured memory_bytes: 48436