#include<iostream>
#include<algorithm>
#include<vector>
constexpr double INFI = 1000000000000000001;
constexpr int BASE = 1000000007;


typedef long long ll;

template<typename T>
T calc_gcd(T a, T b) {
	if (b > a){
    	T w;
      	w=a;
      	a=b;
      	b=w;
    }
	while (a % b) {
		a = a % b;
		swap(a, b);
	}
	return b;
}

using namespace std;
int modpow(int a, int b, int base) {
	vector<int> vb, va;
	while (b != 0) {
		vb.push_back(b % 2);
		b /= 2;
		va.push_back(a);
		a *= a;
		a %= base;
	}
	int ans = 1;
	for (int i = 0;i < vb.size();i++) {
		if (vb[i] == 1) {
			ans *= va[i];
			ans %= base;
		}
	}
	return ans;
}

struct iwasi{
	double a, b;
	double ab;
};

bool operator<=(iwasi x, iwasi y) {
	return x.ab <= y.ab;
}


bool operator<(iwasi x, iwasi y) {
	return x.ab < y.ab;
}

bool operator==(iwasi x, iwasi y) {
	return x.ab == y.ab;
}

int main() {
	int n;
	ll a, b;
	cin >> n;
	iwasi* v = new iwasi[n];
	ll num_0=0;
	int j = 0;
	for (int i = 0;i < n;i++) {
		cin >> a >> b;
		if (a == 0 && b == 0) {
			num_0++;
		}
		else {
			v[j].a = a;
			v[j].b = b;
			if (v[j].a == 0) {
				v[j].ab = -1 / INFI;
			}
			else if (v[j].b == 0) {
				v[j].ab = INFI;
			}
			else {
				a = a / calc_gcd(a, b);
				b = b / calc_gcd(a, b);
				v[j].a = a;
				v[j].b = b;
				v[j].ab = v[j].a / v[j].b;
			}
			j++;
		}
	}
	if (j == 0) {
		cout << num_0 << endl;
		return 0;
	}
	sort(v, v+j);
	vector<pair<iwasi, int>> v2;
	v2.push_back(make_pair(v[0], 1));
	iwasi now = v[0];
	for (int i = 1;i < j;i++) {
		if (v[i] == now) {
			v2[v2.size() - 1].second++;
		}
		else {
			v2.push_back(make_pair(v[i], 1));
			now = v[i];
		}
	}
	vector<double> v3;
	ll sum = 0;
	ll psum = 0;
	for (int i = 0;i < v2.size();i++) {
		v3.push_back(v2[i].first.ab);
	}
	for (int i = 0;i < v2.size();i++) {
		psum = sum;
		if (v2[i].first.ab < 0) {
			sum += (1LL + sum) * ((ll)modpow(2, v2[i].second, BASE) - 1LL);
			sum %= BASE;
			if (v2[i].first.a == 0) {
				if (binary_search(v3.begin(), v3.end(),INFI)) {
					int index = lower_bound(v3.begin(), v3.end(), INFI) - v3.begin();
					sum += (1LL + psum) * ((ll)modpow(2, v2[index].second, BASE) - 1LL);
					sum %= BASE;
				}
			}
			else if (binary_search(v3.begin(), v3.end(),-v2[i].first.b/v2[i].first.a)) {
				int index = lower_bound(v3.begin(), v3.end(), -v2[i].first.b / v2[i].first.a) - v3.begin();
				sum += (1LL + psum) * ((ll)modpow(2,v2[index].second,BASE)-1LL);
				sum %= BASE;
			}
		}else {
			if (v2[i].first.ab == INFI) {
				if (binary_search(v3.begin(), v3.end(), -1 /INFI)) {

				}
				else {
					sum += (1LL + sum) * ((ll)modpow(2, v2[i].second, BASE) - 1LL);
					sum %= BASE;
				}
			}else if (binary_search(v3.begin(), v3.end(), -v2[i].first.b / v2[i].first.a)) {
				
			}
			else {
				sum += (1LL+sum)* ((ll)modpow(2, v2[i].second, BASE) - 1LL);
				sum %= BASE;
			}
		}
	}
	
	cout << sum + num_0 << endl;
}
