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: Wrong Answer)

/*    特徴    */
// mapのkeyにpairを使う
// 座標で考える

/*    教訓    */
// 何かをグループ分けしたい時、バケツは強い
// mapもバケツの進化系
// % より * の方が演算の優先順位が高い
// 引き算のMOD計算の後は、正負判定して負なら+MODする

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

using ll = long long;
using ld  = long double;
const int INF=1e9+7;
const ll LINF=9223372036854775807;
const ll MOD=1e9+7;
const ld PI=acos(-1);
const ld EPS = 1e-9; //微調整用（EPSより小さいと0と判定など）

#define begin_end(a) a.begin(),a.end() //sort(begin_end(vec));
#define REP(i,m,n) for(ll i=(ll)(m) ; i < (ll) (n) ; i++ )
#define rep(i,n) REP(i,0,n)

// -------- template end - //


// - library ------------- //

ll llpow(ll a, ll b){
    if(b == 0){
        return 1;
    }
    ll ans = llpow(a, b / 2);
    ans = ans * ans % MOD;
    if(b % 2 == 1){
        ans = ans * a % MOD;
    }
    return ans;
}

// --------- library end - //



// - main() -------------- //

int main(){


  ll N;
  cin >> N;

  // イワシを入れるための二分割された四角いバケツ
  // key : <a, b>
  // value : <(a, b)であるイワシの数, (-a, b)であるイワシの数>
  // 同じバケツの違うセクションに入れられたイワシ同士は仲が悪い
  // それ以外の組み合わせのイワシは仲が良い（ただし、(0, 0)のイワシは全員と仲が悪い）
  map<pair<ll, ll>, pair<ll, ll> > sardine_buckets;

  // 孤高のイワシ（0, 0)の数
  ll double_zero_sardines = 0;

  rep(i, N){
    ll a, b;
    cin >> a >> b;

    // a, bを既約分数で表す（a, bを同じ割合のまま互いに素にする）
    // つまり、(a, b) の最大公約数で割ればいい
    ll gcd_ab = gcd(a, b);
    // (負, 負) -> (正, 正), (正, 負) -> (負, 正) に統一する
    // C++17 からの gcd() は正の値を返す（特殊な条件で負になることもあるらしいが不明）ので、処理をする必要がある
    // __gcd() を使うなら、__gcd(正, 負) もしくは __gcd(負, 負) とすると負の数を返すようなので、何もしなくても自動でひっくり返る
    if (b < 0){
      a = -a;
      b = -b;
    }

    if (gcd_ab == 0) {
      // 孤高のイワシの場合
      double_zero_sardines++;
    }
    else if (a != 0 && b != 0){
      // 通常のイワシの場合
      a /= gcd_ab;
      b /= gcd_ab;

      // (a, b) = (正, 正)のイワシは、普通に(a, b)のバケツに入れる
      if (a >= 0){
        pair<ll, ll> pair_ab = make_pair(a, b);
        // イワシをセクション1に放り込む
        sardine_buckets[pair_ab].first++;
      }
      // (a, b) = (負, 正)になっているイワシは、(b, -a)のバケツに入れればいいので、正にしてひっくり返す
      // ex) (-3, 2) のイワシは、(2, 3) のイワシと仲が悪いので、(2, 3)のラベルがついたバケツ（のセクション2）に入れればいい
      else {
        a = -a;
        swap(a, b);

        pair<ll, ll> pair_ab = make_pair(a, b);

        // イワシをセクション2に放り込む
        sardine_buckets[pair_ab].second++;
      }
    }
    else {
      // (0, *) or (*, 0) の場合
      pair<ll, ll> pair_ab = make_pair(0, 0);
      if (a == 0) sardine_buckets[pair_ab].first++;
      else sardine_buckets[pair_ab].second++;
    }
  }

  // イワシをバケツに入れ終わったので、後は計算する

  ll ans = 1;
  for (pair<pair<ll, ll>, pair<ll, ll> > p : sardine_buckets){
    ll s_pl = p.second.first; // セクション1に入れられた、(a, b)のイワシ
    ll s_mi = p.second.second; // セクション2に入れられた、(-b, a)のイワシ

    ll tmp = llpow(2, s_pl) + llpow(2, s_mi) - 1;
    // MODが負になっている場合は + MOD
    tmp = ( tmp < 0 ? tmp + MOD : tmp );
    ans = ans * tmp % MOD;
  }
  
  // 孤高のイワシは1つしか入れられない
  ans = (ans + double_zero_sardines) % MOD;

  // 最後に、「0匹のイワシが入っている」というパターンはNGなので、-1
  ans = (ans - 1) % MOD;

  cout << ans << endl;

// ---------- main() end - //
}