#include<bits/stdc++.h>
#define XX first
#define YY second
#define pb emplace_back
#define FOR(i,a,b) for(int (i)=(a);i<(b);++(i))
#define EFOR(i,a,b) for(int (i)=(a);i<=(b);++(i))
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define REP rep
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define all(X) (X).begin(),(X).end()
#define eb emplace_back

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef ll LL;
typedef pii PII;
typedef pll PLL;
const ll MOD=1e9+7;

#define rall(X) (X).rbegin(),(X).rend()
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())
#define reps(X,S,Y) for (int (X) = S;(X) < (Y);++(X))
#define rreps(X,S,Y) for (int (X) = (Y)-1;(X) >= (S);--(X))
template<class T> inline bool MX(T &l,const T &r){return l<r?l=r,1:0;}
template<class T> inline bool MN(T &l,const T &r){return l>r?l=r,1:0;}

int N;
LL A[114514];
LL B[114514];

bool check(int l) {
  LL cur = 0;
  multiset<pll> as, bs;
  rep(i, N) {
    LL d = B[i] - A[i];
    if (d >= 0) {
      bs.insert(pll(B[i], A[i]));
    } else {
      as.insert(pll(A[i], B[i]));
    }
  }

  while (as.size() > l) {
    as.erase(as.find(*as.rbegin()));
  }
  while (as.size() < l && bs.size()) {
    as.insert(pll(bs.begin()->YY, bs.begin()->XX));
    bs.erase(bs.begin());
  }
  if (as.size() < l) return false;
  for (auto &p : as) cur -= p.XX;
  for (auto &p : bs) cur += p.XX - p.YY;

  while (!as.empty() && !bs.empty()) {
    if (bs.begin()->XX < as.rbegin()->XX) {
      cur += as.rbegin()->XX-bs.begin()->XX;
      as.erase(as.find(*as.rbegin()));
      as.insert(pll(bs.begin()->YY, bs.begin()->XX));
      bs.erase(bs.begin());
    } else break;
  }
  return cur >= 0;
}

pll GetAns(int l) {
  assert (l < N);
  LL cur = 0;
  multiset<pll> as, bs;
  rep(i, N) {
    LL d = B[i] - A[i];
    if (d >= 0) {
      bs.insert(pll(B[i], A[i]));
    } else {
      as.insert(pll(A[i], B[i]));
    }
  }

  multiset<pll> cs;
  while (as.size() > l) {
    cs.insert(pll(as.rbegin()->XX, as.rbegin()->YY));
    as.erase(as.find(*as.rbegin()));
  }
  while (as.size() < l && bs.size()) {
    as.insert(pll(bs.begin()->YY, bs.begin()->XX));
    bs.erase(bs.begin());
  }
  assert(as.size() >= l);
  for (auto &p : as) cur -= p.XX;
  for (auto &p : bs) cur += p.XX - p.YY;

  while (!as.empty() && !bs.empty()) {
    if (bs.begin()->XX < as.rbegin()->XX) {
      cs.insert(pll(as.rbegin()->XX, as.rbegin()->YY));
      cur += as.rbegin()->XX-bs.begin()->XX;
      as.erase(as.find(*as.rbegin()));
      as.insert(pll(bs.begin()->YY, bs.begin()->XX));
      bs.erase(bs.begin());
    } else break;
  }

  if (cur == 0) {
    LL p = l;
    LL q = N;
    if (p == 0) return pll(0, 1);
    LL g = __gcd(p, q);
    return pll(p/g, q/g);
  }

  assert(!bs.empty());
  pll ret(cur, bs.begin()->XX);
  for (auto &p : cs) {
    pll tmp(cur+p.YY-p.XX, p.YY);
    assert(tmp.XX < tmp.YY);
    if (tmp.XX*ret.YY > ret.XX*tmp.YY) ret = tmp;
  }

  for (auto &p : as) {
    LL t = bs.begin()->XX;
    if (cs.size()) MN(t, cs.begin()->XX);
    LL v = cur + p.YY - t;
    pll tmp(v, p.YY);
    if (tmp.XX*ret.YY > ret.XX*tmp.YY) ret = tmp;
  }
  ret.XX += l*ret.YY;
  ret.YY *= N;
  LL g = __gcd(ret.XX, ret.YY);
  return pll(ret.XX/g, ret.YY/g);
}

signed main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);

  cin >> N;
  rep(i, N) {
    cin >> A[i] >> B[i];
  }

  int low = 0;
  int high = N+1;
  while (high-low > 1) {
    int mid = (high+low)/2;
    if (check(mid)) low = mid;
    else high = mid;
  }
 
  //cout << low << endl;
  auto ans = GetAns(low);
  cout << ans.XX << " " << ans.YY << endl;
}


Measured memory_bytes: 10112