Buggy python submission (verdict: Runtime Error):
n = int(input())

abl = [map(int, input().split()) for _ in range(n)]

from collections import defaultdict
dic = defaultdict(int)

# a,bの最大公約数
def gcd(a, b):
   while b:
       a, b = b, a % b
   return a

for a,b in abl:
    gc = abs(gcd(a,b))
    if a < 0:
        a, b = -a // gc, -b // gc
    else:
        a, b = a // gc, b // gc
    dic[(a,b)] += 1
MOD = 1000000007
ans = 1
used = defaultdict(int)
for (a,b) in dic:
    if b > 0:
        target = (b, -a)
    else:
        target = (-b, a)
    if target in dic:
        if used[target] == 0:
            ans *= pow(2, dic[(a,b)], MOD) + pow(2, dic[target], MOD) - 1
            used[(a,b)] = 1
    else:
        ans *= (dic[(a,b)] + 1)
    ans %= 1000000007


print(ans - 1)









Fixed submission:
n = int(input())

abl = [map(int, input().split()) for _ in range(n)]

from collections import defaultdict
dic = defaultdict(int)

# a,bの最大公約数
def gcd(a, b):
   while b:
       a, b = b, a % b
   return a

ab0 = 0
a0 = 0
b0 = 0
for a,b in abl:
    if a == 0 and b == 0:
        ab0 += 1
        continue
    elif a == 0:
        a0 += 1
        continue
    elif b == 0:
        b0 += 1
        continue
    gc = abs(gcd(a,b))
    if a < 0:
        a, b = -a // gc, -b // gc
    else:
        a, b = a // gc, b // gc
    dic[(a,b)] += 1
MOD = 1000000007
ans = 1
used = defaultdict(int)
for (a,b) in dic:
    if b > 0:
        target = (b, -a)
    else:
        target = (-b, a)
    if target in dic:
        if used[target] == 0:
            ans *= pow(2, dic[(a,b)], MOD) + pow(2, dic[target], MOD) - 1
            used[(a,b)] = 1
    else:
        ans *= pow(2, dic[(a,b)], MOD)
    ans %= 1000000007

ans *= pow(2, a0, MOD) + pow(2, b0, MOD) - 1
ans %= 1000000007

print((ans - 1 + ab0) % MOD)

Buggy python submission (verdict: Runtime Error):
n = int(input())

abl = [map(int, input().split()) for _ in range(n)]

from collections import defaultdict
dic = defaultdict(int)

for a,b in abl:
    dic[b / a] += 1
MOD = 1000000007
ans = 1
used = defaultdict(int)
for d in dic:
    if -(1/d) in dic:
        if used[-(1/d)] == 0:
            ans *= pow(2, dic[d], MOD) + pow(2, dic[-(1/d)], MOD)  - 1
            used[d] = 1
    else:
        ans *= (dic[d] + 1)
    ans %= 1000000007


print(ans - 1)









Fixed submission:
n = int(input())

abl = [map(int, input().split()) for _ in range(n)]

from collections import defaultdict
dic = defaultdict(int)

# a,bの最大公約数
def gcd(a, b):
   while b:
       a, b = b, a % b
   return a

ab0 = 0
a0 = 0
b0 = 0
for a,b in abl:
    if a == 0 and b == 0:
        ab0 += 1
        continue
    elif a == 0:
        a0 += 1
        continue
    elif b == 0:
        b0 += 1
        continue
    gc = abs(gcd(a,b))
    if a < 0:
        a, b = -a // gc, -b // gc
    else:
        a, b = a // gc, b // gc
    dic[(a,b)] += 1
MOD = 1000000007
ans = 1
used = defaultdict(int)
for (a,b) in dic:
    if b > 0:
        target = (b, -a)
    else:
        target = (-b, a)
    if target in dic:
        if used[target] == 0:
            ans *= pow(2, dic[(a,b)], MOD) + pow(2, dic[target], MOD) - 1
            used[(a,b)] = 1
    else:
        ans *= pow(2, dic[(a,b)], MOD)
    ans %= 1000000007

ans *= pow(2, a0, MOD) + pow(2, b0, MOD) - 1
ans %= 1000000007

print((ans - 1 + ab0) % MOD)