#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
#include <map>

namespace
{
  static std::array<long long, 200001> delicious = {};
  static std::array<long long, 200001> smell = {};

  static std::array<std::vector<double>, 361> rad = {};
  static int  except = {};
  static int  zero_one = {};
  static int  one_zero = {};
  static std::map<std::pair<long long, long long>, long long> fishes = {};
  static std::map<std::pair<long long, long long>, bool> checkes = {};
}


namespace ABC168
{
  static constexpr long long DIV = 1000000007;
  template<typename T>
  void norm(T& num) {
    num = (num + DIV) % DIV;
  }


  template<typename T>
  T gcd(T a, T b) {
    if (b == 0) return a;

    return gcd(b, a % b);
  };

  template<typename T>
  T selectN(T num, T N)
  {
    T accum = 0;
    T val = 1;
    for (auto i = 0; i < N; ++i)
    {
      val *= (num - i);
      norm(val);
    }
    return val;
  }

  template<typename T>
  T selectMoreThanOne(T num)
  {
    T accum = 0;
    T val  = 1;
    T val2 = 1;
    for (auto i = 1; i <= num; ++i)
    {
      val *= (num - i + 1);
      norm(val);
      val2 *= i;
      norm(val2);
      accum += (val/val2);
      norm(accum);
    }
    return accum;
  }


  class E
  {
  public:
    E() = default;
    ~E() = default;

    void Run()
    {

      long long N = 0;
      std::cin >> N;
      for (int i = 0; i < N; ++i)
      {
        long long A = 0;
        long long B = 0;
        std::cin >> A;
        std::cin >> B;

        if (A == 0 && B == 0) {
          except++;
          continue;
        }

        if (A == 0)
        {
          zero_one++;
          continue;
        }
        else if(B==0)
        {
          one_zero++;
          continue;
        }
        

        auto kouyaku = abs(gcd(A, B));

        if (A < 0 && B < 0) {
          A = abs(A);
          B = abs(B);
        }
        else if (A < 0 || B < 0)
        {
          A = -abs(A);
          B = abs(B);
        }

        auto p = std::make_pair(A / kouyaku, B / kouyaku);

        fishes[p]++;
      }

      // パターン全体
      auto answer = 1;

      // (0,1)(1,0)
      {
        long long zo = selectMoreThanOne(zero_one) + 1;
        long long oz = selectMoreThanOne(one_zero) + 1;
        norm(zo); norm(oz);
        answer = zo + oz + 1;
        norm(answer);
      }

      for (auto p : fishes)
      {          
        auto nakawarui = std::make_pair(-p.first.second, p.first.first);
        if (p.first.first < 0)
        {
          nakawarui.first  = abs(nakawarui.first);
          nakawarui.second = abs(nakawarui.second);
        }

        if (checkes.count(nakawarui) > 0) { continue; }

        auto nakawarui_num = (fishes.count(nakawarui) > 0) ? fishes[nakawarui] : 0;

        if (nakawarui_num > 0)
        {
          // どちらかから1匹以上選ぶ方法
          auto A = selectMoreThanOne(p.second);
          auto B = selectMoreThanOne(nakawarui_num);

          // このグルーぷから0匹以上選ぶ
          auto r = A + B + 1;
          norm(r);

          answer *= r;
          norm(answer);

          checkes[p.first] = true;
          checkes[nakawarui] = true;
        }
        else
        {
          auto num = selectMoreThanOne(p.second) + 1;
          norm(num);
          answer *= num;
          norm(answer);
        }
      }

      answer += except - 1;

      std::cout << answer << std::endl;
    }
  };

}
nt main()
{

  ABC168::E prob;
  prob.Run();

  return 0;
}

