from collections import defaultdict



def gcd(x, y):

    if y == 0:

        return x

    else:

        return gcd(y, x % y)



def main():

    MOD = 1000000007

    N = int(eval(input()))

    # Ai * Aj + Bi * Bj = 0

    # -> Ai * Aj = -Bi * Bj

    # -> (Ai/Bi) = -(Aj/Bj)

    # のとき、そのイワシ同士は入れられない



    # そこで、 Ci = Ai/Bi を約分したもの（かつBi>0としておく）

    # を覚えておき、Ci = -Cj となるようなペア同士を数えていく



    C = defaultdict(int)

    n00 = 0

    for i in range(N):

        a, b = list(map(int, input().split()))

        # (0, 0) はどのイワシとも仲が悪いので、考慮の対象から外して置き、

        # 後で(0, 0)のイワシの本数分足す

        if a == 0 and b == 0:

            n00 += 1

            continue



        # Bが0の場合、Aが0のイワシであればなんでも仲が悪くなるので、

        # C = -1 / 0 で統一する。

        if b == 0:

            C[(-1, 0)] += 1

            continue

        # Aが0の場合、Bが0のイワシであればなんでも仲が悪くなるので、

        # C = 0 / 1 で統一する。

        elif a == 0:

            C[(0, 1)] += 1

            continue

        _gcd = gcd(a, b)

        a = a // _gcd

        b = b // _gcd

        # bは常に0以上にする

        if b < 0:

            b = -b

            a = -a

        C[(a, b)] += 1

    

    C = dict(C)

    flag = {k: False for k in list(C.keys())}



    groups = []

    for c, nc in list(C.items()):

        a, b = c

        # 仲の悪いイワシの個数

        bad_a, bad_b = -b, a

        if bad_b < 0:

            bad_b = -bad_b

            bad_a = -bad_a

        nBad = C.get((bad_a, bad_b), 0)

        # 仲の悪いイワシがいなければ、

        # この中からイワシを選ぶ時のすべての組み合わせ（全て選択しない場合を含む）の数を考える

        if nBad == 0:

            groups.append(2 ** nc)

            continue

        # 中の悪いグループがすでに調査済みなら何もしない

        elif flag[(bad_a, bad_b)]:

            continue



        # あるCのイワシがnc本、それと中の悪いイワシがnBad本あるとする。

        # nc + nBad 本のイワシのうち、OKな組み合わせの個数は

        # [nc本から1本以上選ぶ組み合わせ] + [nc本から1本以上選ぶ組み合わせ] + [イワシを全て選択しない場合]

        # (2^nc - 1) + (2^nBad - 1) + 1 = 2^nc + 2^nBad - 1

        groups.append((2 ** nc) + (2 ** nBad) - 1)

        flag[(a, b)] = True



    # 各グループの選択肢を掛け合わせ、-1する

    # (全て選択しないパターンを除外する)

    ans = 1

    for g in groups:

        ans = (ans * g) % MOD

    # -1 するついでに(0, 0) のイワシから1本以上選ぶ場合の数も足しておく

    ans = (ans + n00 - 1) % MOD

    print(ans)





if __name__ == '__main__':

    main()
from collections import defaultdict

import math

import sys

 

read = sys.stdin.buffer.read

readline = sys.stdin.buffer.readline

readlines = sys.stdin.buffer.readlines



def gcd(x, y):

    if y == 0:

        return x

    else:

        return gcd(y, x % y)



def main():

    MOD = 1000000007

    N = int(readline())

    m = list(map(int, read().split()))

    A, B = list(zip(*list(zip(m, m))))

    # Ai * Aj + Bi * Bj = 0

    # -> Ai * Aj = -Bi * Bj

    # -> (Ai/Bi) = -(Aj/Bj)

    # のとき、そのイワシ同士は入れられない



    # そこで、 Ci = Ai/Bi を約分したもの（かつBi>0としておく）

    # を覚えておき、Ci = -Cj となるようなペア同士を数えていく



    C = defaultdict(int)

    n00 = 0

    for a, b in zip(A, B):

        # (0, 0) はどのイワシとも仲が悪いので、考慮の対象から外して置き、

        # 後で(0, 0)のイワシの本数分足す

        if a == 0 and b == 0:

            n00 += 1

            continue



        # Bが0の場合、Aが0のイワシであればなんでも仲が悪くなるので、

        # C = -1 / 0 で統一する。

        if b == 0:

            C[(-1, 0)] += 1

            continue

        # Aが0の場合、Bが0のイワシであればなんでも仲が悪くなるので、

        # C = 0 / 1 で統一する。

        elif a == 0:

            C[(0, 1)] += 1

            continue

        # A / B を約分して、同じ値のイワシの個数を数え上げる

        g = math.gcd(a, b)

        a = a // g

        b = b // g

        # bは常に0以上にする

        if b < 0:

            b = -b

            a = -a

        C[(a, b)] += 1

    

    C = dict(C)

    flag = {k: False for k in list(C.keys())}



    ans = 1

    for c, nc in list(C.items()):

        a, b = c

        a2, b2 = (-b, a) if a >= 0 else (b, -a)

        # 仲の悪いイワシの個数

        nBad = C.get((a2, b2), 0)

        # 仲の悪いイワシがいなければ、

        # この中からイワシを選ぶ時のすべての組み合わせ（全て選択しない場合を含む）の数を考える

        # = 2^nc  = 1 << nc

        if nBad == 0:

            k = 1 << nc

        else:

            # (-2, 3) (3, 2) があるとき、それぞれで組み合わせを考えると重複するので、

            # 片方しか数えないようにする

            if flag[(a2, b2)]:

                continue



            # 仲の悪いイワシがいる場合、

            # あるCのイワシがnc本、それと中の悪いイワシがnBad本あるとする。

            # nc + nBad 本のイワシのうち、OKな組み合わせの個数は

            # [nc本から1本以上選ぶ組み合わせ] + [nc本から1本以上選ぶ組み合わせ] + [イワシを全て選択しない場合]

            # (2^nc - 1) + (2^nBad - 1) + 1 = 2^nc + 2^nBad - 1

            k = (1 << nc) + (1 << nBad) - 1

        

        ans = (ans * k) % MOD

        flag[c] = True



    # 上の数え上げだと、イワシを1本も選ばない場合も含まれているので、

    # そのパターンを除外するため-1する。

    # -1 するついでに(0, 0) のイワシから1本以上選ぶ場合の数も足しておく

    ans = (ans + n00 - 1) % MOD

    print(ans)





if __name__ == '__main__':

    main()
from collections import defaultdict


def gcd(x, y):
    if y == 0:
        return x
    else:
        return gcd(y, x % y)


def main():
    MOD = 1000000007
    N = int(eval(input()))
    # Ai * Aj + Bi * Bj = 0
    # -> Ai * Aj = -Bi * Bj
    # -> (Ai/Bi) = -(Aj/Bj)
    # のとき、そのイワシ同士は入れられない
    # そこで、 Ci = Ai/Bi を約分したもの（かつBi>0としておく）
    # を覚えておき、Ci = -Cj となるようなペア同士を数えていく
    C = defaultdict(int)
    n00 = 0
    for i in range(N):
        a, b = list(map(int, input().split()))
        # (0, 0) はどのイワシとも仲が悪いので、考慮の対象から外して置き、
        # 後で(0, 0)のイワシの本数分足す
        if a == 0 and b == 0:
            n00 += 1
            continue
        # Bが0の場合、Aが0のイワシであればなんでも仲が悪くなるので、
        # C = -1 / 0 で統一する。
        if b == 0:
            C[(-1, 0)] += 1
            continue
        # Aが0の場合、Bが0のイワシであればなんでも仲が悪くなるので、
        # C = 0 / 1 で統一する。
        elif a == 0:
            C[(0, 1)] += 1
            continue
        _gcd = gcd(a, b)
        a = a // _gcd
        b = b // _gcd
        # bは常に0以上にする
        if b < 0:
            b = -b
            a = -a
        C[(a, b)] += 1
    C = dict(C)
    flag = {k: False for k in list(C.keys())}
    groups = []
    for c, nc in list(C.items()):
        a, b = c
        # 仲の悪いイワシの個数
        bad_a, bad_b = -b, a
        if bad_b < 0:
            bad_b = -bad_b
            bad_a = -bad_a
        nBad = C.get((bad_a, bad_b), 0)
        # 仲の悪いイワシがいなければ、
        # この中からイワシを選ぶ時のすべての組み合わせ（全て選択しない場合を含む）の数を考える
        if nBad == 0:
            groups.append(2**nc)
            continue
        # 中の悪いグループがすでに調査済みなら何もしない
        elif flag[(bad_a, bad_b)]:
            continue
        # あるCのイワシがnc本、それと中の悪いイワシがnBad本あるとする。
        # nc + nBad 本のイワシのうち、OKな組み合わせの個数は
        # [nc本から1本以上選ぶ組み合わせ] + [nc本から1本以上選ぶ組み合わせ] + [イワシを全て選択しない場合]
        # (2^nc - 1) + (2^nBad - 1) + 1 = 2^nc + 2^nBad - 1
        groups.append((2**nc) + (2**nBad) - 1)
        flag[(a, b)] = True
    # 各グループの選択肢を掛け合わせ、-1する
    # (全て選択しないパターンを除外する)
    ans = 1
    for g in groups:
        ans = (ans * g) % MOD
    # -1 するついでに(0, 0) のイワシから1本以上選ぶ場合の数も足しておく
    ans = (ans + n00 - 1) % MOD
    print(ans)


if __name__ == "__main__":
    main()

from collections import defaultdict
import math
import sys

read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines


def gcd(x, y):
    if y == 0:
        return x
    else:
        return gcd(y, x % y)


def main():
    MOD = 1000000007
    N = int(readline())
    m = list(map(int, read().split()))
    A, B = list(zip(*list(zip(m, m))))
    # Ai * Aj + Bi * Bj = 0
    # -> Ai * Aj = -Bi * Bj
    # -> (Ai/Bi) = -(Aj/Bj)
    # のとき、そのイワシ同士は入れられない
    # そこで、 Ci = Ai/Bi を約分したもの（かつBi>0としておく）
    # を覚えておき、Ci = -Cj となるようなペア同士を数えていく
    C = defaultdict(int)
    n00 = 0
    for a, b in zip(A, B):
        # (0, 0) はどのイワシとも仲が悪いので、考慮の対象から外して置き、
        # 後で(0, 0)のイワシの本数分足す
        if a == 0 and b == 0:
            n00 += 1
            continue
        # Bが0の場合、Aが0のイワシであればなんでも仲が悪くなるので、
        # C = -1 / 0 で統一する。
        if b == 0:
            C[(-1, 0)] += 1
            continue
        # Aが0の場合、Bが0のイワシであればなんでも仲が悪くなるので、
        # C = 0 / 1 で統一する。
        elif a == 0:
            C[(0, 1)] += 1
            continue
        # A / B を約分して、同じ値のイワシの個数を数え上げる
        g = math.gcd(a, b)
        a = a // g
        b = b // g
        # bは常に0以上にする
        if b < 0:
            b = -b
            a = -a
        C[(a, b)] += 1
    C = dict(C)
    flag = {k: False for k in list(C.keys())}
    ans = 1
    for c, nc in list(C.items()):
        a, b = c
        a2, b2 = (-b, a) if a >= 0 else (b, -a)
        # 仲の悪いイワシの個数
        nBad = C.get((a2, b2), 0)
        # 仲の悪いイワシがいなければ、
        # この中からイワシを選ぶ時のすべての組み合わせ（全て選択しない場合を含む）の数を考える
        # = 2^nc  = 1 << nc
        if nBad == 0:
            k = 1 << nc
        else:
            # (-2, 3) (3, 2) があるとき、それぞれで組み合わせを考えると重複するので、
            # 片方しか数えないようにする
            if flag[(a2, b2)]:
                continue
            # 仲の悪いイワシがいる場合、
            # あるCのイワシがnc本、それと中の悪いイワシがnBad本あるとする。
            # nc + nBad 本のイワシのうち、OKな組み合わせの個数は
            # [nc本から1本以上選ぶ組み合わせ] + [nc本から1本以上選ぶ組み合わせ] + [イワシを全て選択しない場合]
            # (2^nc - 1) + (2^nBad - 1) + 1 = 2^nc + 2^nBad - 1
            k = (1 << nc) + (1 << nBad) - 1
        ans = (ans * k) % MOD
        flag[c] = True
    # 上の数え上げだと、イワシを1本も選ばない場合も含まれているので、
    # そのパターンを除外するため-1する。
    # -1 するついでに(0, 0) のイワシから1本以上選ぶ場合の数も足しておく
    ans = (ans + n00 - 1) % MOD
    print(ans)


if __name__ == "__main__":
    main()

+import math +import sys + +read = sys.stdin.buffer.read +readline = sys.stdin.buffer.readline +readlines = sys.stdin.buffer.readlines -    N = int(eval(input())) +    N = int(readline()) +    m = list(map(int, read().split())) +    A, B = list(zip(*list(zip(m, m)))) -    for i in range(N): -        a, b = list(map(int, input().split())) +    for a, b in zip(A, B): -        _gcd = gcd(a, b) -        a = a // _gcd -        b = b // _gcd +        # A / B を約分して、同じ値のイワシの個数を数え上げる +        g = math.gcd(a, b) +        a = a // g +        b = b // g -    groups = [] +    ans = 1 +        a2, b2 = (-b, a) if a >= 0 else (b, -a) -        bad_a, bad_b = -b, a -        if bad_b < 0: -            bad_b = -bad_b -            bad_a = -bad_a -        nBad = C.get((bad_a, bad_b), 0) +        nBad = C.get((a2, b2), 0) +        # = 2^nc  = 1 << nc -            groups.append(2**nc) -            continue -        # 中の悪いグループがすでに調査済みなら何もしない -        elif flag[(bad_a, bad_b)]: -            continue -        # あるCのイワシがnc本、それと中の悪いイワシがnBad本あるとする。 -        # nc + nBad 本のイワシのうち、OKな組み合わせの個数は -        # [nc本から1本以上選ぶ組み合わせ] + [nc本から1本以上選ぶ組み合わせ] + [イワシを全て選択しない場合] -        # (2^nc - 1) + (2^nBad - 1) + 1 = 2^nc + 2^nBad - 1 -        groups.append((2**nc) + (2**nBad) - 1) -        flag[(a, b)] = True -    # 各グループの選択肢を掛け合わせ、-1する -    # (全て選択しないパターンを除外する) -    ans = 1 -    for g in groups: -        ans = (ans * g) % MOD +            k = 1 << nc +        else: +            # (-2, 3) (3, 2) があるとき、それぞれで組み合わせを考えると重複するので、 +            # 片方しか数えないようにする +            if flag[(a2, b2)]: +                continue +            # 仲の悪いイワシがいる場合、 +            # あるCのイワシがnc本、それと中の悪いイワシがnBad本あるとする。 +            # nc + nBad 本のイワシのうち、OKな組み合わせの個数は +            # [nc本から1本以上選ぶ組み合わせ] + [nc本から1本以上選ぶ組み合わせ] + [イワシを全て選択しない場合] +            # (2^nc - 1) + (2^nBad - 1) + 1 = 2^nc + 2^nBad - 1 +            k = (1 << nc) + (1 << nBad) - 1 +        ans = (ans * k) % MOD +        flag[c] = True +    # 上の数え上げだと、イワシを1本も選ばない場合も含まれているので、 +    # そのパターンを除外するため-1する。