// Slower C++ solution:
#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/tree_policy.hpp>



using namespace std;

using namespace __gnu_pbds;



#define fi first

#define se second

#define mp make_pair

#define pb push_back

#define fbo find_by_order

#define ook order_of_key



typedef long long ll;

typedef pair<ll,ll> ii;

typedef vector<ll> vi;

typedef long double ld; 

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;

typedef set<int>::iterator sit;

typedef map<int,int>::iterator mit;

typedef vector<int>::iterator vit;



ll a[101];

ll b[101];

ll dp[4][301][101];

ll sum[4][101];



int main()

{

	ios_base::sync_with_stdio(0); cin.tie(0);

	ll n; ll w;

	cin>>n>>w;

	for(int i=0;i<n;i++)

	{

		cin>>a[i]>>b[i];

	}

	ll ans=0;

	for(int i=0;i<=n;i++)

	{

		vector<ll> vec[4];

		memset(dp,0,sizeof(dp));

		memset(sum,0,sizeof(sum));

		ll ww = w-ll(i)*a[0];

		ww=min(ww,3LL*i);

		if(ww<0) continue;

		for(int j=0;j<n;j++)

		{

			vec[a[j]-a[0]].pb(b[j]);

		}

		for(int j=0;j<4;j++) sort(vec[j].rbegin(),vec[j].rend());

		for(int j=0;j<4;j++)

		{

			for(int k=0;k<vec[j].size();k++)

			{

				sum[j][k]=vec[j][k];

				if(k>0) sum[j][k]+=sum[j][k-1];

			}

		}

		for(int j=0;j<vec[0].size();j++)

		{

			dp[0][0][j+1] = sum[0][j];

		}

		for(int j=0;j<3;j++)

		{

			for(int k=0;k<=ww;k++)

			{

				for(int l=0;l<=i;l++)

				{

					//cerr<<j<<' '<<k<<' '<<l<<' '<<dp[j][k][l]<<'\n';

					ll val = dp[j][k][l];

					dp[j+1][k][l]=max(dp[j+1][k][l],val);

					for(int m=0;m<vec[j+1].size();m++)

					{

						if(l+m+1<=i&&k+(j+1)*(m+1)<=ww)

						{

							dp[j+1][k+(j+1)*(m+1)][l+m+1]=max(dp[j+1][k+(j+1)*(m+1)][l+m+1],val+sum[j+1][m]);

						}

					}

				}

			}

		}

		ll an=0;

		for(int k=0;k<=ww;k++)

		{

			an=max(an,dp[3][k][i]);

		}

		//cerr<<i<<' '<<ww<<' '<<an<<'\n';

		ans=max(ans,an);

	}

	cout<<ans<<'\n';

}


// Faster C++ solution for the same problem (measured speedup: 2.3767567757418746x):
#include <bits/stdc++.h>

using namespace std;



using VS = vector<string>;    using LL = long long;

using VI = vector<int>;       using VVI = vector<VI>;

using PII = pair<int, int>;   using PLL = pair<LL, LL>;

using VL = vector<LL>;        using VVL = vector<VL>;



#define ALL(a)  begin((a)),end((a))

#define RALL(a) (a).rbegin(), (a).rend()

#define PB push_back

#define EB emplace_back

#define MP make_pair

#define SZ(a) int((a).size())

#define SORT(c) sort(ALL((c)))

#define RSORT(c) sort(RALL((c)))

#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)

#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)

#define debug(x) cerr << #x << ": " << x << endl

const int INF = 1e9;                          const LL LINF = 1e16;

const LL MOD = 1000000007;                    const double PI = acos(-1.0);

int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };



/* -----  2018/02/23  Problem: 073_arc_b / Link: https://arc073.contest.atcoder.jp/tasks/arc073_b?lang=en  ----- */

/* ------問題------



あなたは N 個の物と、強度 W のバッグを持っています。 i 個目の物は、重さが wi で価値が vi です。

あなたは、物のうちいくつかを選び、バッグに入れます。 ただし、選んだ物の重さの和は W 以下でなくてはいけません。

あなたは、バッグに入れた物の価値の総和を最大化したいです。



-----問題ここまで----- */

/* -----解説等-----



昔はDPを気合で解いていたけど、これはw[0] からの値が4種類しかないのでどれを何個使うかで全探索できる。

dpのときはdp(i,j,k):=i個目まで見てj個選択し,余計な重さがkのときの最大値として、

O(N^3)で解ける。



----解説ここまで---- */



LL N, W;



LL ans = 0LL;



int main() {

	cin.tie(0);

	ios_base::sync_with_stdio(false);



	cin >> N >> W;

	VL w(N), v(N);



	VVL s(4,VL());

	LL baseW;

	FOR(i, 0, N) {

		cin >> w[i] >> v[i];

		if (i == 0)baseW = w[i];

		int id = w[i] - baseW;

		s[id].push_back(v[i]);

	}

	FOR(i, 0, 4)RSORT(s[i]);





	FOR(i, 0, SZ(s[0])+1) {

		FOR(j, 0, SZ(s[1])+1) {

			FOR(k, 0, SZ(s[2])+1) {

				FOR(l, 0, SZ(s[3])+1) {



					LL Vs = 0;

					LL Ws = 0;

					FOR(a, 0, i) {

						Ws += baseW;

						Vs += s[0][a];

					}FOR(a, 0, j) {

						Ws += baseW+1;

						Vs += s[1][a];

					}FOR(a, 0, k) {

						Ws += baseW+2;

						Vs += s[2][a];

					}FOR(a, 0, l) {

						Ws += baseW+3;

						Vs += s[3][a];

					}

					if (W >= Ws) {

						ans = max(ans, Vs);

					}



				}

			}

		}

	}

	cout << ans << "\n";



	return 0;

}