#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
    #define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
    #define eprintf(...) 42
#endif

using ll = long long;
using ld = long double;
using D = double;
using uint = unsigned int;
template<typename T>
using pair2 = pair<T, T>;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second

#ifdef LOCAL
__int128 abs(__int128 a)
{
	return a > 0 ? a : -a;
}
#endif

__int128 gcd(__int128 a, __int128 b)
{
	return a == 0 ? b : gcd(b % a, a);
}

struct frac
{
	__int128 up, down;
	
	frac() {}
	frac(__int128 up_, __int128 down_)
	{
		up = up_;
		down = down_;
		
		__int128 g = gcd(abs(up), abs(down));
		up /= g;
		down /= g;
		if (down < 0)
		{
			up *= -1;
			down *= -1;
		}
	}
};

inline frac operator+(const frac &a, const frac &b)
{
	return frac(a.up * b.down + a.down * b.up, a.down * b.down);
}

inline bool operator<(const frac &a, const frac &b)
{
	return a.up * b.down < b.up * a.down;
}

const int maxn = 100005;
const ll inf = 1e18;

vector<pair2<int>> fast, slow;
ll sumbfast[maxn];
int n;
ll totald;

frac solvefast(ll tA)
{
	int pos = lower_bound(sumbfast, sumbfast + (int)fast.size(), -totald - tA) - sumbfast;
	if (pos != 0)
	{
		ll tB2 = sumbfast[pos - 1];
		ll up = -totald - tA - tB2;
		ll down = fast[pos - 1].se;
		up = min(up, down);
		assert(up >= 0);
		return frac(pos - 1, n) + frac(up, n * down);
	}
	return frac(0, 1);
}

int main()
{
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		if (x <= y) fast.pb({x, y});
		else slow.pb({x, y});
	}
	sort(all(fast), [&] (pair2<int> &a, pair2<int> &b) {return a.se < b.se; });
	sumbfast[0] = 0;
	for (int i = 0; i < (int)fast.size(); i++) sumbfast[i + 1] = sumbfast[i] + fast[i].se;
	sort(all(slow), [&] (pair2<int> &a, pair2<int> &b) {return a.fi < b.fi; });
	
	totald = 0;
	for (auto t : fast) totald += t.fi - t.se;
	
	ll totaldslow = 0;
	ll minB = inf;
	ll tB = 0;
	ll tA = 0;
	frac answer = solvefast(0);
	for (int i = 0; i < (int)slow.size(); i++)
	{
		totaldslow += slow[i].fi - slow[i].se;
		tB += slow[i].se;
		minB = min(minB, (ll)slow[i].se);
		tB -= minB;
		if (tB > -(totald + totaldslow)) break;
		ll up = -(totald + totaldslow) - tB;
		tB += minB;
		up = min(up, (ll)minB);
		frac curans = frac(i, n) + frac(up, n * minB);
		//cout << i << ' ' << curans.up << ' ' << curans.down << endl;
		//cout << totald << ' ' << totaldslow << ' ' << tB << ' ' << minB << endl;
		//cout << up << ' ' << frac(up, n * minB).up << endl;
		
		tA += slow[i].fi;
		curans = curans + solvefast(tA);
		//cout << i << ' ' << curans.up << ' ' << curans.down << endl;
		if (answer < curans) answer = curans;
	}
	printf("%lld %lld\n", (ll)answer.up, (ll)answer.down);
    return 0;
}
