#include <bits/stdc++.h>
using namespace std;
constexpr long long int MOD = 1000000007;
constexpr double EPS = 1e-8;
long long int N, M, K, H, W, L, R;
struct Node {
  long long int a, b, index;
  Node(const int aa, const int bb, const int ii) {
    a = aa, b = bb, index = ii;
    return;
  }
  bool operator<(const Node& n) const { return b - a < n.b - n.a; }
};
class Add_Segment_Tree {
  vector<long long int> v;
  vector<int> l;
  vector<int> r;
  long long int ret;
  int num;
  long long int Update(int place) {
    if (place >= v.size() / 2) {
      return v[place];
    }
    v[place] = Update(place * 2) + Update(place * 2 + 1);
    return v[place];
  }
  void Sum(int a, int b, int place) {
    if (l[place] >= a && r[place] <= b) {
      ret += v[place];
      return;
    }
    if (l[place] > b || r[place] < a) return;
    Sum(a, b, place * 2);
    Sum(a, b, place * 2 + 1);
    return;
  }

 public:
  void Left(int place) {
    if (place >= v.size() / 2) {
      l[place] = place - v.size() / 2;
      return;
    }
    Left(place * 2);
    Left(place * 2 + 1);
    l[place] = l[place * 2];
    return;
  }
  void Right(int place) {
    if (place >= v.size() / 2) {
      r[place] = place - v.size() / 2;
      return;
    }
    Right(place * 2);
    Right(place * 2 + 1);
    r[place] = r[place * 2 + 1];
    return;
  }
  Add_Segment_Tree(int n) {
    n++;
    num = 1;
    while (num < n * 2) num *= 2;
    l.resize(num);
    r.resize(num);
    v.resize(num, 0);
    Left(1);
    Right(1);
  }
  void Add(int place, long long int num, bool update) {
    place += v.size() / 2;
    v[place] += num;
    if (!update) return;
    place /= 2;
    while (place) {
      v[place] = v[place * 2] + v[place * 2 + 1];
      place /= 2;
    }
  }
  void TopDown() { Update(1); }
  long long int Sum(int a, int b) {
    ret = 0;
    Sum(a, b, 1);
    return ret;
  }
};
long long int gcd(long long int a, long long int b) {
  while (b) {
    a %= b;
    swap(a, b);
  }
  return a;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> N;
  vector<Node> v;
  vector<pair<int, int>> w;
  for (int i = 0; i < N; i++) {
    cin >> L >> R;
    v.push_back(Node(L, R, i));
    w.push_back({R, i});
  }
  sort(w.begin(), w.end());
  sort(v.begin(), v.end());
  reverse(v.begin(), v.end());
  vector<int> indexv(N);
  vector<int> indexw(N);
  for (int i = 0; i < N; i++) {
    indexv[v[i].index] = i;
    indexw[w[i].second] = i;
  }
  vector<int> converter(N);
  for (int i = 0; i < N; i++) {
    converter[indexv[i]] = indexw[i];
  }
  Add_Segment_Tree asg(N);
  Add_Segment_Tree num(N);
  long long int c = 0, p = 1;
  long long int suma = 0;
  for (int i = 0; i < N; i++) {
    suma += v[i].a;
    asg.Add(converter[i], v[i].b, true);
    num.Add(converter[i], 1, true);
    L = -1, R = N;
    while (R - L > 1) {
      int mid = (L + R) / 2;
      long long box = asg.Sum(mid, N);
      if (box < suma)
        R = mid;
      else
        L = mid;
    }
    int usednum = 0;
    if (!R) continue;
    if (L) {
      usednum += num.Sum(0, L - 1);
    }
    long long int box = asg.Sum(L, N);
    long long int np = asg.Sum(L, L);
    long long int nc = box - suma + np * usednum;
    np *= N;
    if (c == 0) {
      p = np, c = nc;
      long long int g = gcd(c, p);
      c /= g, p /= g;
    } else {
      if (log(c) + log(np) < log(p) + log(nc)) {
        c = nc, p = np;
        long long int g = gcd(c, p);
        c /= g, p /= g;
      }
    }
  }
  cout << c << " " << p << endl;
}
