import Control.Monad
import Control.Monad.Trans.State.Strict
import Data.Char (isSpace)
import Data.Maybe (fromJust)
import qualified Data.ByteString.Lazy.Char8 as B

type Parser a = StateT B.ByteString Maybe a

parseInt :: Parser Int
parseInt = StateT (B.readInt . B.dropWhile isSpace)

parseInt2 :: Parser (Int,Int)
parseInt2 = liftM2 (,) parseInt parseInt

parse :: Parser [(Int,Int)]
parse = do
    n<-parseInt
    replicateM n parseInt2

main=do
    tas<-fromJust.evalStateT parse <$> B.getContents
    print.liftM2 (+) fst snd.foldl1 f $ tas

f (u,v) (t,a) = (t*n, a*n)
    where
        n = 1 + (bsearch (g (u,v) (t,a)) (-1, (u+v)*(t+a)))

-- [a,b) -> a .. f aがTrueとなる最大のa, f bはFalse
-- aとbは評価しないので、範囲が0..(n-1)のとき、(a,b)=(-1,n)で呼んで良い
bsearch f (a,b)
    | a+1 == b = a
    | f m  = bsearch f (m,b)
    | True = bsearch f (a,m)
    where m = (a + (b-a)`div`2)

g (a,b) (c,d) n = or[(c+d)*n<a+b, c*n<a, d*n<b]
