Problem:
Score: 500 points

Problem Statement

We have caught N sardines. The deliciousness and fragrantness of the i-th sardine is A_i and B_i, respectively.

We will choose one or more of these sardines and put them into a cooler. However, two sardines on bad terms cannot be chosen at the same time.

The i-th and j-th sardines (i \neq j) are on bad terms if and only if A_i \cdot A_j + B_i \cdot B_j = 0.

In how many ways can we choose the set of sardines to put into the cooler? Since the count can be enormous, print it modulo 1000000007.

Constraints

All values in input are integers.

1 \leq N \leq 2 \times 10^5

-10^{18} \leq A_i, B_i \leq 10^{18}

Input

Input is given from Standard Input in the following format:

N
A_1 B_1
:
A_N B_N

Output

Print the count modulo 1000000007.

Sample Input 1

3
1 2
-1 1
2 -1

Sample Output 1

5

There are five ways to choose the set of sardines, as follows:

The 1-st

The 1-st and 2-nd

The 2-nd

The 2-nd and 3-rd

The 3-rd

Sample Input 2

10
3 2
3 2
-1 1
2 -1
-3 -9
-8 12
7 7
8 1
8 2
8 4

Sample Output 2

479

Solution in C++ (GCC 9.2.1) (judge verdict: Runtime Error)

#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>  
#include <ext/pb_ds/tree_policy.hpp>   
using namespace std;
using namespace __gnu_pbds;  
typedef tree<int, null_type, less<int>, rb_tree_tag,  tree_order_statistics_node_update>  ordered_set; 
#define num 1000000007
//#define num 998244353
#define REP(i,a,n) for(ll i=a;i<n;i++)
#define inarr(i,a,n,A) for(ll i=a;i<n;i++) { cin>>A[i]; }
#define vll vector<long long>
#define pii pair <int,int>
#define pll pair<long long, long long>
#define vpii vector< pair <int,int>>
#define vpll vector< pair<long long, long long>>
//#define max(a,b) ((a>b)?a:b)
//#define min(a,b) ((a>b)?b:a)
#define max3(a,b,c) ((a>b)?(a>c)?a:c:(b>c)?b:c)
#define min3(a,b,c) ((a<b)?(a<c)?a:c:(b<c)?b:c)
#define avg(a,b) ((a)+(b))/2
#define pb push_back
#define pob pop_back
#define sf int flag=0     //Remember semicolon
// #define assmin(a,b) if(b<=a) { a=b; }
// #define assmax(a,b) if(b>=a) { a=b; }
#define f first
#define s second
#define fix(f,n) std::fixed<<std::setprecision(n)<<f
#define all(x) x.begin(), x.end()
#define M_PI 3.14159265358979323846
#define epsilon (double)(0.00000000001)
#define side 1e9
#define watch(x) cout << (#x) << " is " << (x) << endl
typedef long long ll;
 
ll mod_exp(ll a, ll b, ll c)
{
	ll res=1;
	a=a%c;
	while(b>0)
	{
		if(b%2==1)
		{
			res=(res*a)%c;
		}
		b/=2;
		a=(a*a)%c;
	}
	return res;
}
ll mymod(ll a,ll b)
{
    return ((a%b)+b)%b;
}
// bool prime[200001];
// void SieveOfEratosthenes() 
// { 
//     memset(prime, true, sizeof(prime)); 
//     prime[1]=false;
//     for (int p=2; p*p<=200000; p++) 
//     { 
//         if (prime[p] == true) 
//         { 
//             for (int i=p*p; i<=200000; i += p) 
//                 prime[i] = false; 
//         } 
//     } 
//     return;
// }
// ll powe[200005];
// void power()
// {
//     powe[0]=1;
//     REP(i,1,200005)
//     {
//         powe[i]=mymod(2*powe[i-1],num);
//     }
// }
// ll gcdExtended(ll,ll,ll *,ll *);
// ll modInverse(ll a, ll m) 
// { 
//     ll x, y; 
//     ll g = gcdExtended(a, m, &x, &y); 
//         ll res = (x%m + m) % m;
//         return res;
// } 
// ll gcdExtended(ll a, ll b, ll *x, ll *y) 
// { 
//     if (a == 0) 
//     { 
//         *x = 0, *y = 1; 
//         return b; 
//     } 
//     ll x1, y1; 
//     ll gcd = gcdExtended(b%a, a, &x1, &y1); 
//     *x = y1 - (b/a) * x1; 
//     *y = x1; 
//     return gcd; 
// }
// struct node
// {
// 	vll adj;
//     ll indegree;
// };

ll seg_tree[487348];

void build(ll pre[], ll v, ll left, ll right)
{
    if(left==right)
    {
        seg_tree[v] = pre[left];
        return;
    }
    else
    {
        ll mid = (left+right)/2;
        build(pre, 2*v, left, mid);
        build(pre,2*v+1, mid+1, right);
        seg_tree[v] = max(seg_tree[2*v], seg_tree[2*v+1]);
    }
}
ll query(ll v, ll left, ll right, ll l, ll r)
{
    if(l>r)
    {
        return LLONG_MIN;
    }
    if(left==l && right==r)
    {
        return seg_tree[v];
    }
    ll mid=(left+right)/2;
    ll a = query(2*v, left, mid, l, min(r,mid));
    ll b = query(2*v+1, mid+1, right, max(l,mid+1), r);
    return max(a,b);
}

ll solve(vector<vll> v, ll x)
{
    ll n = v.size();
    ll m = v[0].size();
    ll dp[n][m];
    REP(i,0,n)
    {
        REP(j,0,m)
        {
            dp[i][j] = 1e18;
        }
    }
    dp[0][0]=v[0][0] - x;
    REP(i,0,n)
    {
        REP(j,0,m)
        {
            if(v[i][j]<x) continue;
            if(!i && !j) continue;
            else if(i==0)
            {
                dp[i][j] = (dp[i][j-1] + v[i][j] - x);
            }
            else if(j==0)
            {
                dp[i][j] = (dp[i-1][j] + v[i][j] - x);
            }
            else
            {
                dp[i][j] = min(dp[i][j-1], dp[i-1][j]) + v[i][j] - x;
            }
        }
    }
    return dp[n-1][m-1];
}

double solve(ll h, ll m)
{
    double a1 = h*30.0 + (m/60.0)*30.0;
    double a2 = 6.0*m;
    return abs(a2-a1);
}
void reduce(ll &a, ll &b)
{
    ll g=__gcd(a,b);
    a/=g;
    b/=g;
    if(b<0) { a*=-1; b*=-1;}
    return;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll n;
    cin>>n;
    map<pll,ll> m;
    map<pll,ll> done;
    REP(i,0,n)
    {
        ll a,b;
        cin>>a>>b;
        reduce(a,b);
        m[{a,b}]++;
    }
    vpll v;
    ll ind=0;
    for(auto itr=m.begin(); itr!=m.end(); ++itr)
    {
        if(done[itr->first])
        {
            continue;
        }
        pll search = {-itr->first.s, itr->first.f};
        if(itr->first.f<0)
        {
            search.f*=-1;
            search.s*=-1;
        }
        if(m.find(search)==m.end())
        {
            ind+=itr->second;
            done[itr->first]=true;
        }
        else
        {
            v.pb({itr->second, m[search]});
            done[search] = done[itr->first] = 1;
        }
        done[itr->first] = 1;
    }
    ll ans = mod_exp(2, ind, num);
    for(auto x: v)
    {
        ll temp = mymod(mod_exp(2,x.f,num) + mod_exp(2,x.s,num) -1, num);
        ans = mymod(ans*temp, num);
    }
    ans--;
    cout<<ans<<"\n";
    return 0;
}