/*
AtCoderBeginnerContest168
Problem E - ∙ (Bullet) / Bullet
Time Limit: 2 sec / Memory Limit: 1024 MB
Score: 500 points
*/

#include <iostream>
#include <vector>
#include <map>

int MODULUS = 1000000007;

long add(long x, long y) { long res = x+y; res %= MODULUS; return res; }
long mult(long x, long y) { long res = x*y; res %= MODULUS; return res; }

std::vector<long> pow;

void initPow(int n)
{
    long curr = 1;
    for (int i=0; i<=n; i++) { pow.push_back(curr); curr = add(curr, curr); }
}

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

class Group;
std::map<std::string, Group*> groups;

class Group
{
public:
    Group(long A, long B)
    {
        if (A<0)
        {
            A *= -1;
            B *= -1;
        }
        long D = gcd(A,abs(B));
        if (D==0) //these sardines can only ever be alone!
        {
            _a = 0;
            _b = 0;
            _plusCnt = 1;
            _minusCnt = 0;
        }
        else
        {
            if (A==0) // but D<>0 ==> B <>0
            {
//std::cerr << "doink-a\n";
                _a = 1;
                _b = 0;
                _plusCnt = 0;
                _minusCnt = 1;
            }
            else if (B==0) // but D<>0 ==> A <>0
            {
//std::cerr << "doink-b\n";
                _a = 1;
                _b = 0;
                _plusCnt = 1;
                _minusCnt = 0;
            }
            else //A>0, B<>0
            {
                A /= D;
                B /= D;
                if (B>0)
                {
                    _a = A;
                    _b = B;
                    _plusCnt = 1;
                    _minusCnt = 0;
                }
                else // B<0
                {
                    _a = -B;
                    _b = A;
                    _plusCnt = 0;
                    _minusCnt = 1;
                }
            }
        }
        _key = std::to_string(_a) + ";" + std::to_string(_b);
        assert(_a >=0);
        assert(_plusCnt + _minusCnt == 1);
        assert(_plusCnt * _minusCnt == 0);
//show();
    }
    void Assimilate(Group* that)
    {
        //better have this->_key and that->_key be the same!
        this->_plusCnt += that->_plusCnt;
        this->_minusCnt += that->_minusCnt;
    }
    static void IncrementGroup(long A, long B)
    {
        Group *g = new Group(A, B);
        std::string key = g->_key;
        if (groups.count(key)==0)
        {
            groups.insert(std::pair<std::string, Group*>(key, g));
        }
        else
        {
            groups[key]->Assimilate(g);
        }
    }

    int PlusCount() { return _plusCnt; }
    int MinusCount() { return _minusCnt; }
    std::string Key() { return _key; }

    void show()
    {
        std::cerr << "A: " << _a << "; B: " << _b << "; plusCnt: " <<
                                _plusCnt << "; minusCnt: " << _minusCnt << "\n";
    }

private:
    long _a, _b;
    int _plusCnt, _minusCnt;
    std::string _key;
};

int main()
{
    int N;
    std::cin >> N;

    initPow(N);
    for (int i=0; i<N; i++)
    {
        long A, B;
        std::cin >> A >> B;
        Group::IncrementGroup(A, B);
    }
//std::cerr << "Group Count = " << groups.size() << "\n";

    long res = 1;
    std::map<std::string, Group*>::iterator it;
    for (it = groups.begin(); it != groups.end(); it++)
    {
//it->second->show();
        if (it->first == "0;0") continue;
        Group *g = it->second;
        int p = g->PlusCount();
        int m = g->MinusCount();
        long factor = add(pow[p], pow[m]);
        factor = add(factor, -1); //OK to add -1 since won't get a negative intermediate result
        res = mult(res, factor);
    }
    res--; // remove case where there are no sardines

    if (groups.count("0;0")==1)
    {
        res = add(res, groups["0;0"]->PlusCount());
    }
    std::cout << res << "\n";
}
