#include <bits/stdc++.h>
using namespace std;
const int maxn = 100100;
struct node {
  int A, B;
} a[maxn];
struct val {
  long long x, y;
  void operator=(const int &B) { x = B, y = 1; }
};
void print(val A) { printf("val=%lld/%lld\n", A.x, A.y); }
val operator+(const val &A, const int B) {
  val ret = A;
  ret.x = ret.x + B * A.y;
  return ret;
}
bool operator<(const val &A, const val &B) { return A.x * B.y < B.x * A.y; }
bool operator<(const node &A, const node &B) { return A.A < B.A; }
bool cmp(const node &A, const node &B) { return A.B < B.B; }
priority_queue<node> q;
void chkmax(val &A, val B) { A = A < B ? B : A; }
long long gcd(long long x, long long y) {
  long long r;
  while (y) {
    r = x % y;
    x = y;
    y = r;
  }
  return x;
}
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d%d", &a[i].A, &a[i].B);
  sort(a + 1, a + n + 1, cmp);
  long long tot = 0, sum = 0;
  int cnt = 0;
  val ans, st;
  ans = 0, st = 0;
  for (int i = 1; i <= n; i++)
    if (a[i].A < a[i].B) tot += a[i].B - a[i].A;
  for (int i = 1; i <= n; i++) {
    while (sum > tot) {
      sum -= (q.top()).A;
      cnt--;
      q.pop();
    }
    if (a[i].A < a[i].B) {
      if (tot - sum >= a[i].B)
        st = cnt + 1;
      else {
        st = (val){tot - sum, a[i].B};
        st = st + cnt;
      }
      chkmax(ans, st);
      tot -= a[i].B - a[i].A;
      while (sum > tot) {
        sum -= (q.top()).A;
        cnt--;
        q.pop();
      }
    }
    if (a[i].A <= (tot - sum))
      st = cnt + 1;
    else {
      st = (val){a[i].A - (tot - sum), a[i].B};
      if (st.x > st.y)
        st.x = 0;
      else
        st.x = st.y - st.x;
      st = st + cnt;
    }
    chkmax(ans, st);
    q.push(a[i]);
    sum += a[i].A;
    cnt++;
  }
  if (ans.x == 0) {
    printf("0 1\n");
    return 0;
  }
  ans.y *= n;
  long long r = gcd(ans.x, ans.y);
  ans.x /= r, ans.y /= r;
  printf("%lld %lld\n", ans.x, ans.y);
  return 0;
}
