//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

#define shandom_ruffle random_shuffle

using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;
const int nax=10*1000*1007;
const ll mod=998244353;
using ld=long double;

int n;

pll tab[nax];

vi moje, jego;

pll best{0, 1};

bool operator < (pll a, pll b)
{
	return a.first*(ld)b.second<b.first*(ld)a.second;
}

//~ pll daj(int g)
//~ {
	//~ pods=0;
	//~ li=0;
	//~ mi=1;
	//~ ll ja=0;
	//~ ll on=0;
	//~ for (int i=1; i<=g; i++)
	//~ {
		//~ ja+=tab[i].second.first;
		//~ on+=tab[i].second.second;
	//~ }
	//~ if (ja>=on)
		//~ return {0, 1};
	//~ mi=1;
	//~ for (int i=1; i<=g; i++)
	//~ {
		//~ if (on-tab[i].second.second>=ja)
		//~ {
			//~ pods++;
			//~ on-=tab[i].second.second;
		//~ }
		//~ else
		//~ {
			//~ ll mni=on-tab[i].second.second;
			//~ ll dlu=on;
			//~ ll mog=ja-mni;
			//~ li=dlu-mog;
			//~ mi=dlu*n;
			//~ break;
		//~ }
	//~ }
	//~ li=li*n+pods*mi;
	//~ mi*=n;
	//~ ll gg=__gcd(li, mi);
	//~ li/=gg;
	//~ mi/=gg;
	//~ return {li, mi};
//~ }

int check(int v)
{
	vll minip;
	for (int i : jego)
		minip.push_back(tab[i].first);
	vector <pll> roz;
	for (int i : moje)
		roz.push_back({tab[i].second-tab[i].first*2, tab[i].first});
	sort(minip.begin(), minip.end());
	sort(roz.begin(), roz.end());
	reverse(roz.begin(), roz.end());
	for (int i=1; i<(int)minip.size(); i++)
		minip[i]+=minip[i-1];
	ll sp=0;
	ll sr=0;
	for (pll i : roz)
		sr+=i.first+i.second;
	//~ debug() << imie(minip);
	//~ debug() << imie(roz);
	for (int i=0; i<=(int)roz.size() && i<=v; i++)
	{
		int tam=v-i;
		if (tam<=(int)minip.size())
		{
			ll czas=sp;
			if (tam)
				czas+=minip[tam-1];
			if (czas<=sr)
				return 1;
		}
		if (i<(int)roz.size())
		{
			sp+=roz[i].second;
			sr-=roz[i].first+roz[i].second;
		}
	}
	return 0;
}

ll summinip[nax];
ll sumsr[nax];
ll sumsp[nax];

void probuj(int v)
{
	vector <pll> minip;
	for (int i : jego)
		minip.push_back({tab[i].first, tab[i].second});
	vector <pll> roz;
	for (int i : moje)
		roz.push_back({tab[i].second-tab[i].first*2, tab[i].first});
	sort(minip.begin(), minip.end());
	sort(roz.begin(), roz.end());
	reverse(roz.begin(), roz.end());
	
	for (int i=1; i<=(int)minip.size(); i++)
		summinip[i]=summinip[i-1]+minip[i-1].first;
	for (int i=1; i<=(int)roz.size(); i++)
	{
		sumsr[i]=sumsr[i-1]+roz[i-1].first+roz[i-1].second;
		sumsp[i]=sumsp[i-1]+roz[i-1].second;
	}
	int rozm=minip.size();
	int rozz=roz.size();
	//~ debug() << imie(minip) << imie(roz);
	for (int h=0; h<(int)minip.size(); h++)
	{
		int tsa=v-(int)minip.size()-1;
		tsa=max(tsa, 0);
		int tsb=min(v, (int)roz.size());
		if (tsa>tsb)
			continue;
		while(tsa<tsb)
		{
			int ts1=(tsa+tsb)>>1;
			int ts2=(tsa+tsb+2)>>1;
			ll roza=sumsr[rozz]-sumsr[ts1]-(sumsp[ts1]+summinip[v-ts1]);
			if (v-ts1>=h+1)
				roza-=(minip[v-ts1+1].first-minip[h].first);
			ll rozb=sumsr[rozz]-sumsr[ts2]-(sumsp[ts2]+summinip[v-ts2]);
			if (v-ts2>=h+1)
				rozb-=(minip[v-ts2+1].first-minip[h].first);
			if (roza>=rozb)
				tsb=ts1;
			else
				tsa=ts2;
		}
		int ts1=tsa;
		ll roza=sumsr[rozz]-sumsr[ts1]-(sumsp[ts1]+summinip[v-ts1]);
		if (v-ts1>=h+1)
			roza-=(minip[v-ts1+1].first-minip[h].first);
		if (roza<0)
			continue;
		//~ debug() << imie(roza) << imie(minip[h]) << " " << (minip[h].first-roza);
		//~ debug() << "nom1";
		assert(roza<=minip[h].first);
		ll li=minip[h].second-(minip[h].first-roza);
		ll mi=minip[h].second;
		if (li<0)
			continue;
		//~ assert((minip[h].first-roza)<=minip[h].second);
		
		li=li+v*mi;
		mi*=n;
		ll g=__gcd(li, mi);
		li/=g;
		mi/=g;
		pll kan={li, mi};
		if (best<kan)
			best=kan;
	}
	//~ return;
	for (int h=0; h<(int)roz.size(); h++)
	{
		int tsa=v-(int)minip.size();
		tsa=max(tsa, 0);
		int tsb=min(v, (int)roz.size()-1);
		if (tsa>tsb)
			continue;
		while(tsa<tsb)
		{
			int ts1=(tsa+tsb)>>1;
			int ts2=(tsa+tsb+2)>>1;
			ll roza=sumsr[rozz]-sumsr[ts1]-(sumsp[ts1]+summinip[v-ts1]);
			if (ts1>=h+1)
			{
				roza+=roz[h].second;
				roza-=roz[ts1].first+roz[ts1].second;
				roza-=roz[ts1].second;
			}
			else
			{
				roza-=roz[h].first+roz[h].second;
			}
			ll rozb=sumsr[rozz]-sumsr[ts2]-(sumsp[ts2]+summinip[v-ts2]);
			if (ts2>=h+1)
			{
				rozb+=roz[h].second;
				rozb-=roz[ts2].first+roz[ts2].second;
				rozb-=roz[ts2].second;
			}
			else
			{
				rozb-=roz[h].first+roz[h].second;
			}
			if (roza>=rozb)
				tsb=ts1;
			else
				tsa=ts2;
		}
		int ts1=tsa;
		ll roza=sumsr[rozz]-sumsr[ts1]-(sumsp[ts1]+summinip[v-ts1]);
		if (ts1>=h+1)
		{
			roza+=roz[h].second;
			roza-=roz[ts1].first+roz[ts1].second;
			roza-=roz[ts1].second;
		}
		else
		{
			roza-=roz[h].first+roz[h].second;
		}
		if (roza<0)
			continue;
		//~ debug() << imie(roza) << imie(minip[h]) << " " << (minip[h].first-roza);
		//~ debug() << "nom2";
		assert(roza<=roz[h].second);
		ll li=roz[h].first+2*roz[h].second-(roz[h].second-roza);
		ll mi=roz[h].first+2*roz[h].second;
		//~ ll li=minip[h].second-(minip[h].first-roza);
		//~ ll mi=minip[h].second;
		if (li<0)
			continue;
		
		li=li+v*mi;
		mi*=n;
		ll g=__gcd(li, mi);
		li/=g;
		mi/=g;
		pll kan={li, mi};
		if (best<kan)
			best=kan;
	}
}

int main()
{
	scanf("%d", &n);
	for (int i=1; i<=n; i++)
	{
		ll a, b;
		scanf("%lld%lld", &a, &b);
		tab[i]={a, b};
		if (a<=b)
			moje.push_back(i);
		else
			jego.push_back(i);
	}
	//~ sort(tab+1, tab+1+n);
	//~ reverse(tab+1, tab+1+n);
	int bsa=0;
	int bsb=n;
	while(bsa<bsb)
	{
		int bss=(bsa+bsb+2)>>1;
		if (check(bss))
			bsa=bss;
		else
			bsb=bss-1;
	}
	assert(bsa<n);
	//~ debug() << imie(bsa);
	best={bsa, n};
	ll g=__gcd(bsa, n);
	best.first/=g;
	best.second/=g;
	probuj(bsa);
	
	//~ debug() << check(2);
	
	//~ auto wez=daj(g);
	//~ while()
	printf("%lld %lld\n", best.first, best.second);
	return 0;
}
