#include <algorithm>
#include <array>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <optional>
#include <queue>
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

int64_t read_int() {
    int64_t ret = 0, sgn = 1;
    int ch = getchar_unlocked();
    while (isspace(ch)) { ch = getchar_unlocked(); }
    if (ch == '-') { sgn = -1; ch = getchar_unlocked(); }
    for (; isdigit(ch); ch = getchar_unlocked())
        ret = (ret * 10) + (ch - '0');
    ungetc(ch, stdin);
    return sgn * ret;
}

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define FOR(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define ALL(c) (c).begin(), (c).end()

template <typename T> inline void assign_min(T& x, const T& value) noexcept { x = min(x, value); }
template <typename T> inline void assign_max(T& x, const T& value) noexcept { x = max(x, value); }

constexpr char LF = '\n';

//-------------------------------------------------------------------------------------------------
#include <boost/operators.hpp>

// a を m で割った余り(>=0)を返す。
constexpr inline int mod(int a, int m) noexcept {
    int r = a % m;
    return r < 0 ? r + m : r;
}

// ax + by = gcd(a, b) を満たすような整数 x,y を返す。
template<int MOD>
pair<int64_t, int64_t> exgcd(int a, int b) noexcept {
    if (b == 0) return {1, 0};
    auto [x, y] = exgcd<MOD>(b, a%b);
    return {y, x-(a/b)*y};
}

// a の逆元を返す。a は MOD と互いに素でなければならない。
template<int MOD>
inline int inverse(int a) noexcept {
    return mod(exgcd<MOD>(MOD, a).second, MOD);
}

template<int MOD>
struct ModInt : private boost::operators<ModInt<MOD>> {
    int value;
    constexpr ModInt() noexcept : value(0) {}
    constexpr explicit ModInt(int value) noexcept
        : value(mod(value, MOD)) {}
    constexpr ModInt<MOD>& operator+=(const ModInt<MOD>& rhs) noexcept {
        value += rhs.value;
        if (value > MOD) value -= MOD;
        return *this;
    }
    constexpr ModInt<MOD>& operator-=(const ModInt<MOD>& rhs) noexcept {
        value -= rhs.value;
        if (value < 0) value += MOD;
        return *this;
    }
    constexpr ModInt<MOD>& operator*=(const ModInt<MOD>& rhs) noexcept {
        value = ((int64_t)value * rhs.value) % MOD;
        return *this;
    }
    ModInt<MOD>& operator/=(const ModInt<MOD>& rhs) noexcept {
        value = ((int64_t)value * inverse<MOD>(rhs.value)) % MOD;
        return *this;
    }
    constexpr bool operator<(const ModInt<MOD>& rhs) const noexcept {
        return value < rhs.value;
    }
    constexpr bool operator==(const ModInt<MOD>& rhs) const noexcept {
        return value == rhs.value;
    }
};
template<int MOD>
ostream& operator<<(ostream& os, const ModInt<MOD>& rhs) {
    os << rhs.value;
    return os;
}
template<int MOD>
istream& operator>>(istream& is, ModInt<MOD>& rhs) {
    int i; is >> i;
    rhs.value = mod(i, MOD);
    return is;
}

// a^n を返す。
template<int MOD>
ModInt<MOD> pow_mod(ModInt<MOD> a, int64_t n) {
    auto ans = ModInt<MOD>(1);
    while (n > 0) {
        if (n & 1) ans *= a;
        a *= a;
        n >>= 1;
    }
    return ans;
}
#include <boost/rational.hpp>

using mint = ModInt<1000000007>;
using Ratio = boost::rational<int64_t>;

int main() {
    int N = read_int();
    vector<int64_t> A(N), B(N);
    REP(i, N) {
        A[i] = read_int();
        B[i] = read_int();
    }

    mint n_zero(0);

    // A[i]A[j] + B[i]B[j] == 0
    // <=> A[i]/B[i] == -B[j]/A[j]

    // key: A[i]/B[i], value: 個数
    map<Ratio, int> R;
    REP(i, N) {
        if (A[i] == 0 && B[i] == 0) {
            n_zero += mint(1);
        } else if (B[i] == 0) {
            Ratio r(numeric_limits<int64_t>::max());
            R[r] += 1;
        } else {
            Ratio r(A[i], B[i]);
            R[r] += 1;
        }
    }

    mint ans(1);
    for (auto [r, cnt] : R) {
        if (cnt == 0) continue;
        Ratio q;
        if (r == 0) {
            q = numeric_limits<int64_t>::max();
        } else {
            q = -1 / r;
        }
        if (R.count(q) == 0) {
            ans *= pow_mod(mint(2), cnt);
        } else {
            int cnt2 = R[q];
            ans *= pow_mod(mint(2), cnt) + pow_mod(mint(2), cnt2) - mint(1);
            R[q] = 0;
        }
    }
    ans += n_zero;
    ans -= mint(1);

    cout << ans << LF;
}


Measured memory_bytes: 18168