#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using ull = uint64_t;

const ll MODVAL = 1000000007LL;

ll modfunc(ll a) {
    if (a >= 0) {
        return a % MODVAL;
    } else {
        ll bb = ((-a) % MODVAL);
        if (bb == 0) {
            return 0;
        } else {
            return MODVAL - bb;
        }
    }
}

ll mod_pow(ll x, ll n) {
    if (n == 0) {
        return 1;
    }
    ll res = mod_pow(x * x % MODVAL, n / 2);
    if (n & 1) {
        res = res * x % MODVAL;
    }
    return res;
}

ll mod(ll a, ll b) {
    if (a >= 0) {
        return a % b;
    } else {
        int64_t bb = ((-a) % b);
        if (bb == 0) {
            return 0;
        } else {
            return b - bb;
        }
    }
}

ll gcd(ll a, ll b) {
    if (b == 0) {
        return a;
    }
    return gcd(b, a % b);
}

bool is_prime(ll n) {
    if (n <= 1) {
        return false;
    }
    for (ll i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

void print() { cout << endl; }
template <typename Head, typename... Tail>
void print(Head head, Tail... tail) {
    int size = sizeof...(Tail);
    cout << head;
    if (size > 0) {
        cout << " ";
    }
    print(tail...);
}

void print0() {}
template <typename Head, typename... Tail>
void print0(Head head, Tail... tail) {
    cout << head;
    print0(tail...);
}

struct xstruct {
    ll val;
};
bool operator<=(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val <= rhs.val;
}
bool operator<(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val < rhs.val;
}
bool operator>=(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val >= rhs.val;
}
bool operator>(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val > rhs.val;
}
bool operator==(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val == rhs.val;
}
bool operator!=(const xstruct& lhs, const xstruct& rhs) {
    return lhs.val != rhs.val;
}
ostream& operator<<(ostream& os, xstruct const& xst) {
    return os << xst.val;
}

struct iwasi {
    int sign;
    ll bunsi;
    ll bunbo;
};
bool operator<=(const iwasi& lhs, const iwasi& rhs) {
    if (lhs.sign == rhs.sign) {
        if (lhs.bunsi == rhs.bunsi) {
            return lhs.bunbo <= rhs.bunbo;
        }
        return lhs.bunsi <= rhs.bunsi;
    }
    return lhs.sign <= rhs.sign;
}
bool operator<(const iwasi& lhs, const iwasi& rhs) {
    if (lhs.sign == rhs.sign) {
        if (lhs.bunsi == rhs.bunsi) {
            return lhs.bunbo < rhs.bunbo;
        }
        return lhs.bunsi < rhs.bunsi;
    }
    return lhs.sign < rhs.sign;
}
bool operator>=(const iwasi& lhs, const iwasi& rhs) {
    if (lhs.sign == rhs.sign) {
        if (lhs.bunsi == rhs.bunsi) {
            return lhs.bunbo >= rhs.bunbo;
        }
        return lhs.bunsi >= rhs.bunsi;
    }
    return lhs.sign >= rhs.sign;
}
bool operator>(const iwasi& lhs, const iwasi& rhs) {
    if (lhs.sign == rhs.sign) {
        if (lhs.bunsi == rhs.bunsi) {
            return lhs.bunbo > rhs.bunbo;
        }
        return lhs.bunsi > rhs.bunsi;
    }
    return lhs.sign > rhs.sign;
}
bool operator==(const iwasi& lhs, const iwasi& rhs) {
    if (lhs.sign == rhs.sign) {
        if (lhs.bunsi == rhs.bunsi) {
            return lhs.bunbo == rhs.bunbo;
        }
    }
    return false;
}
bool operator!=(const iwasi& lhs, const iwasi& rhs) {
    return !(lhs == rhs);
}
int main() {
    ll N;
    cin >> N;

    map<iwasi, ll> iwasis;
    ll zeroiwasi = 0;
    for (ll i = 0; i < N; i++) {
        ll a;
        ll b;
        cin >> a >> b;
        iwasi iw;
        if (b == 0 && a == 0) {
            zeroiwasi++;
            continue;
        } else if (a == 0) {
            iw = iwasi{sign : 0, bunsi : 1, bunbo : 0};
        } else if (b == 0) {
            iw = iwasi{sign : 0, bunsi : 0, bunbo : 1};
        } else {
            int sign = 1;
            if (a < 0) {
                a = -a;
                sign = -sign;
            }
            if (b < 0) {
                b = -b;
                sign = -sign;
            }
            ll g = gcd(a, b);
            iw = iwasi{sign : sign, bunsi : a / g, bunbo : b / g};
        }
        if (iwasis.count(iw) == 0) {
            iwasis[iw] = 0;
        }
        iwasis[iw]++;
    }

    ll frees = N - zeroiwasi;
    ll total = 1;
    set<iwasi> done;
    for (auto iww : iwasis) {
        iwasi iw = iww.first;
        iwasi rev = {sign : -iw.sign, bunsi : iw.bunbo, bunbo : iw.bunsi};
        if (done.count(iw) > 0) {
            continue;
        }
        done.insert(iw);
        done.insert(rev);
        if (iwasis.count(rev)) {
            ll iwacls = iww.second;
            ll revcls = iwasis[rev];
            frees = frees - iwacls - revcls;
            ll mult = (mod_pow(2, iwacls) + mod_pow(2, revcls) - 1) % MODVAL;
            total = (total * mult) % MODVAL;
        }
    }
    total = (total * mod_pow(2, frees)) % MODVAL;
    total = modfunc(total - 1 + zeroiwasi);  // 一匹もいない場合を除去. 0,0のイワシを一匹のみ入れるのは可
    print(total);
}


Measured memory_bytes: 44020