unittest
{
	assert( [ "4 6", "2 1", "3 4", "4 10", "3 4" ].parse.expand.solve == 11 );
	assert( [ "4 6", "2 1", "3 7", "4 10", "3 6" ].parse.expand.solve == 13 );
	assert( [ "4 10", "1 100", "1 100", "1 100", "1 100" ].parse.expand.solve == 400 );
	assert( [ "4 1", "10 100", "10 100", "10 100", "10 100" ].parse.expand.solve == 0 );
}



import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto nw = input.front.split.to!( long[] );
	auto wvs = new long[ 2 ][ nw[ 0 ] ];
	foreach( ref wv; wvs )
	{
		input.popFront;
		wv = input.front.split.to!( long[] );
	}
	return tuple( nw[ 1 ], wvs );
}

auto solve( long wt, long[ 2 ][] wvs )
{
	wvs.multiSort!( ( a, b ) => b[ 0 ] < a[ 0 ], ( a, b ) => b[ 1 ] < a[ 1 ] );
	
	// 重さごとに分けて、価値の高い順で累積和表を作成
	auto sss = new long[][ 4 ];
	auto wm = wvs[ 0 ][ 0 ];
	foreach( i, ref ss; sss )
	{
		ss = [ 0 ];
		while( !wvs.empty && wvs.front[ 0 ] == wm - i )
		{
			ss ~= ss[ $ - 1 ] + wvs.front[ 1 ];
			wvs.popFront;
		}
	}
	
	// 重さwt以内で価値が最大になるパターンを全検索
	auto ans = 0L;
	foreach( c1, s1; sss[ 0 ] )
	{
		auto w1 = wm * c1;
		if( wt < w1 ) break;
		
		foreach( c2, s2; sss[ 1 ] )
		{
			auto w2 = ( wm - 1 ) * c2;
			if( wt < w1 + w2 ) break;
			
			foreach( c3, s3; sss[ 2 ] )
			{
				auto w3 = ( wm - 2 ) * c3;
				if( wt < w1 + w2 + w3 ) break;
				
				foreach( c4, s4; sss[ 3 ] )
				{
					auto w4 = ( wm - 3 ) * c4;
					if( wt < w1 + w2 + w3 + w4 ) break;
					
					ans = max( ans, s1 + s2 + s3 + s4 );
				}
			}
		}
	}
	return ans;
}
