-- I'm expecting a TLE.
import qualified Data.ByteString.Char8 as BC
import Data.Maybe
import Data.List
import Data.Function (on)

type Value = Int
type Weight = Int
newtype Thing = Th (Weight, Value) deriving (Show)

weight :: Thing -> Weight
weight (Th (w,_)) = w
value :: Thing -> Value
value (Th (_, v)) = v

-- SMALLEST to LARGEST
knap' :: [Thing] -> Weight -> [Thing]
knap' [] _ = []
knap' [t] w = if weight t > w
                then []
                else [t]
knap' (t:ts) w = if weight t > w
                   then []
                   else maxByValue (t:knap' ts (w- weight t)) (knap' ts w)

maxBy :: Ord a => (b -> a) -> b -> b -> b
maxBy f x y = case (compare `on` f) x y of
                   LT -> y
                   _ -> x
maxByValue :: [Thing] -> [Thing] -> [Thing]
maxByValue = maxBy (sum . map value)

main = do
    [_, w] <- map read . words <$> getLine
    things <- sortBy (compare `on` weight) <$> readThings
    print . sum . map value $ knap' things w

readThings :: IO [Thing]
readThings = map readThing . BC.lines <$> BC.getContents
    where
        readThing l =
            let [w,v] = map (fst . fromJust . BC.readInt) . BC.words $ l
                in Th (w,v)