#include <bits/stdc++.h>
using ll = long long;
ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  else
    return gcd(b, a % b);
}
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
const int mod = 1e9 + 7;
struct mint {
  long long x;
  mint(long long x = 0) : x((x % mod + mod) % mod) {}
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod) x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const {
    mint res(*this);
    return res += a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res -= a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res *= a;
  }
  bool operator>(const mint a) const {
    mint res(*this);
    return res.x > a.x;
  }
  bool operator<(const mint a) const {
    mint res(*this);
    return res.x < a.x;
  }
  mint pow(long long t) const {
    if (!t) return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1) a *= *this;
    return a;
  }
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return (*this) *= a.inv(); }
  mint operator/(const mint a) const {
    mint res(*this);
    return res /= a;
  }
};
constexpr int premax = 200020;
std::array<mint, premax> f, rf;
bool mymodflag = false;
mint nCk(int n, int k) {
  if (n == k) return mint(1);
  if (n < k) return mint(0);
  if (!mymodflag) {
    f[0] = 1;
    for (int i = 1; i < premax; i++) f[i] = f[i - 1] * i;
    rf[premax - 1] = f[premax - 1].pow(mod - 2);
    for (int i = premax - 2; i >= 0; i--) rf[i] = rf[i + 1] * (i + 1);
    mymodflag = true;
  }
  return f[n] * rf[n - k] * rf[k];
}
mint nPk(int n, int k) {
  if (n < k) return mint(0);
  if (!mymodflag) {
    f[0] = 1;
    for (int i = 1; i < premax; i++) f[i] = f[i - 1] * i;
    rf[premax - 1] = f[premax - 1].pow(mod - 2);
    for (int i = premax - 2; i >= 0; i--) rf[i] = rf[i + 1] * (i + 1);
    mymodflag = true;
  }
  return f[n] * rf[n - k];
}
template <class Monoid>
class SegmentTree {
 private:
  using T = typename Monoid::T;
  using size_type = std::size_t;
  size_type n;
  std::vector<T> data;
  void prop(int i) { data[i] = Monoid::op(data[2 * i], data[2 * i + 1]); }

 public:
  SegmentTree() : n(0) {}
  SegmentTree(int n, T initial = Monoid::identity()) : n(n) {
    data.resize(n * 2, initial);
    for (int i = n - 1; i > 0; i--)
      data[i] = Monoid::op(data[i * 2], data[i * 2 + 1]);
  }
  template <class InputIter,
            class = typename std::iterator_traits<InputIter>::value_type>
  SegmentTree(InputIter first, InputIter last)
      : SegmentTree(distance(first, last)) {
    std::copy(first, last, data.begin() + n);
    for (int i = n - 1; i > 0; i--) prop(i);
  }
  SegmentTree(std::vector<T> v) : SegmentTree(v.begin(), v.end()) {}
  SegmentTree(std::initializer_list<T> v) : SegmentTree(v.begin(), v.end()) {}
  void set(size_t i, const T &v) {
    data[i += n] = v;
    while (i >>= 1) prop(i);
  }
  void add(size_t i, const T &v) {
    data[i += n] += v;
    while (i >>= 1) prop(i);
  }
  T get(size_t i) { return data[i + n]; }
  T fold(int l, int r) {
    if (l < 0) l = 0;
    if (l >= r) return Monoid::identity();
    if (r > int(n)) r = n;
    T tmpL = Monoid::identity(), tmpR = Monoid::identity();
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) tmpL = Monoid::op(tmpL, data[l++]);
      if (r & 1) tmpR = Monoid::op(data[--r], tmpR);
    }
    return Monoid::op(tmpL, tmpR);
  }
  size_type size() { return n; }
};
constexpr long long inf_monoid = 1e18 + 100;
struct Nothing {
  using T = char;
  using Monoid = Nothing;
  using M = T;
  static constexpr T op(const T &, const T &) { return T(); }
  static constexpr T identity() { return T(); }
  template <class X>
  static constexpr X actInto(const M &, long long, const X &x) {
    return x;
  }
};
template <class U = long long>
struct RangeSum {
  using T = U;
  static T op(const T &a, const T &b) { return a + b; }
  static constexpr T identity() { return T(0); }
};
int main(void) {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  int N;
  std::cin >> N;
  std::vector<double> A(N), B(N);
  for (int i = 0; i < (int)(N); i++) std::cin >> A[i] >> B[i];
  std::vector<double> D(N);
  for (int i = 0; i < (int)(N); i++) D[i] = B[i] / A[i];
  std::sort((D).begin(), (D).end());
  std::vector<mint> dp(N);
  SegmentTree<RangeSum<mint>> sg(N);
  for (int i = 0; i < (int)(N); i++) {
    if (i == 0)
      dp[i] = 1;
    else {
      auto low = std::lower_bound(D.begin(), std::next(D.begin(), i), -D[i]);
      auto up = std::upper_bound(D.begin(), std::next(D.begin(), i), -D[i]);
      int s = std::distance(D.begin(), low);
      int e = std::distance(D.begin(), up);
      dp[i] = sg.fold(0, i) - sg.fold(s, e);
    }
    sg.set(i, dp[i]);
  }
  mint ans = 0;
  for (int i = 0; i < (int)(N); i++) ans += dp[i];
  std::cout << ans.x << std::endl;
  return 0;
}
