// 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.3991778590729522x):
#include<bits/stdc++.h>



using namespace std;



using ll=long long;



int main(){

    ll N,W;

    cin>>N>>W;

    vector<vector<int>>t(4);

    ll ww;

    int vv;

    cin>>ww>>vv;

    t[0].push_back(vv);

    for(int i=1;i<N;++i){

        int w,v;

        cin>>w>>v;

        t[w-ww].push_back(v);

    }

    sort(t[0].begin(),t[0].end(),greater<int>());

    sort(t[1].begin(),t[1].end(),greater<int>());

    sort(t[2].begin(),t[2].end(),greater<int>());

    sort(t[3].begin(),t[3].end(),greater<int>());

    for(int i=0;i<4;++i){

        int pre=0;

        for(auto& x:t[i]){

            x += pre;

            pre=x;

        }

    }

    t[0].insert(t[0].begin(),0);

    t[1].insert(t[1].begin(),0);

    t[2].insert(t[2].begin(),0);

    t[3].insert(t[3].begin(),0);

    int ans=0;

    for(ll i=0;i<=t[0].size()-1;++i){

        for(ll j=0;j<=t[1].size()-1;++j){

            for(ll k=0;k<=t[2].size()-1;++k){

                for(ll l=0;l<=t[3].size()-1;++l){

                    if(W<ww*(i+j+k+l)+j+2*k+3*l){

                        break;

                    }

                    ans=max(ans,t[0][i]+t[1][j]+t[2][k]+t[3][l]);

                }

            }

        }

    }

    cout<<ans<<endl;

}