// Standard Stuff
#include <bits/stdc++.h>
using namespace std;

// Macros
#define PRAGMA(x) _Pragma(#x)
//
#define F  first
#define S  second
#define PB push_back
#define MP make_pair
//
#define ALL(container)   container.begin(),container.end()
#define MAKE_UNIQUE(vec) do { PRAGMA(message "DO NOT FORGET TO SORT THE VECTOR !!!"); vec.erase(unique(ALL(vec)),vec.end()); } while(0)
// vec.resize() sucks, use vec.assign()
// comparator -> return <

// Rename Datatypes
using ll  = long long;
using ld  = long double;
using pii = std::pair <int,int>;

// Common Functions
ll fastpow(ll a, ll ex){ ll res = 1; while(ex){ if(ex & 1) res *= a; a *= a; ex >>= 1; } return res; }
ll fastpow(ll a, ll ex, ll m){ a %= m; ll res = 1; while(ex){ if(ex & 1) res = (a*res) % m; a = (a*a) % m; ex >>= 1; } return res; }
ll modinverse(ll a, ll m){ ll m0 = m, y = 0, x = 1; while (a > 1){ ll q = a / m; a %= m; swap(a,m); x -= q*y; swap(x,y); } if(x < 0) x += m0; return x; }

// Output, Common Containers
template <typename T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ' '; return os; }
template <typename T> ostream& operator << (ostream &os, const set<T> &v)    { for (T i : v) os << i << ' '; return os; }
template <typename T> ostream& operator << (ostream &os, const deque<T> &v)  { for (T i : v) os << i << ' '; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const pair<T,S> &v) { os << "(" << v.F << "=>" << v.S << ") "; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const map<T,S> &v)  { for (auto i : v) os << i << ' '; return os; }

// Debugging
#ifdef LOCAL
	#define trace(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); d__f(_it, args); }
	void d__f(__attribute__((unused)) istream_iterator<string> it) {}
	template<typename Head, typename... Tail> void d__f(istream_iterator<string> it, Head H, Tail... T) { cerr << *it << " <=> [" << H << "]\n"; d__f(++it, T...); }
#else
	#define trace(args...)
#endif


// CODE STARTS HERE

const int mod = 1000000007;

signed main() {
	std::ios::sync_with_stdio(false); //Warning: Do NOT use C I/O now.
	std::cin.tie(nullptr); //Note: Comment out this line for interactive questions.
	// std::cout.setf(std::ios::fixed); std::cout.precision(20); //Note: To output decimals correctly.

	// int tt; cin >> tt;
	// for(int test_no = 1; test_no <= tt; ++test_no){}

	int n;
	cin >> n;

	using pll = pair<ll,ll>; 

	vector<pll> arr(n);
	map<pll,pii> m;

	int fs0 = 0;

	for(auto& [f,s]: arr){
		cin >> f >> s;

		if(f == 0 and s == 0) ++fs0; 
		else if(f == 0) ++m[{0,1}].F;
		else if(s == 0) ++m[{0,1}].S;
		else{
			if(s < 0){
				f *= -1;
				s *= -1;
			}

			ll g = gcd(abs(f),abs(s));
			f /= g, s /= g;

			if(f > 0) ++m[{f,s}].F;
			else ++m[{s,-f}].S;
		}
	}

	trace(m);

	ll ans = 1;

	// ai/bi != -bj/aj
	for(auto [ratio,p] : m){
		ll ans_here = fastpow(2, p.F, mod);
		if(p.S){
			ans_here -= 1; // nothing taken
			ans_here += fastpow(2, p.S, mod); 
		}

		ans_here %= mod;

		ans = (ans * ans_here) % mod;
	}

	// nothing taken
	ans = (ans - 1 + mod) % mod;

	// can only take atmost one from {0,0} sardines
	ans = (ans + fs0) % mod;

	cout << ans << "\n";
}


Measured memory_bytes: 18744