// Original C++ solution (slower):
#include <bits/stdc++.h>

//---------------------------

using namespace std;

//---------------------------

#define REP(i,n) for(int i = 0; i < (n); i++)



long long N,W,sm=0;

long long w[200];

long long v[200];

vector<long long> v1,v2,v3,v4;

int i,j,k,l,con;

int cnt[4];



int main(){

  std::ios::sync_with_stdio(false);

  std::cin.tie(0);



  cin >> N >> W;



  REP(i,N){

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

    if(i == 0){

      v1.push_back(v[i]);

    }

    if(i>=1){

      con=w[i]-w[0];

      if(con==0)v1.push_back(v[i]);

      if(con==1)v2.push_back(v[i]);

      if(con==2)v3.push_back(v[i]);

      if(con==3)v4.push_back(v[i]);

    }

  }

  sort(v1.begin(), v1.end());

  sort(v2.begin(), v2.end());

  sort(v3.begin(), v3.end());

  sort(v4.begin(), v4.end());



  reverse(v1.begin(), v1.end());

  reverse(v2.begin(), v2.end());

  reverse(v3.begin(), v3.end());

  reverse(v4.begin(), v4.end());



  for(i=0;i<(int)v1.size();i++){

    if(i+1==(int)v1.size())continue;

    v1[i+1]+=v1[i];

  }

  for(i=0;i<(int)v2.size();i++){

    if(i+1==(int)v2.size())continue;

    v2[i+1]+=v2[i];

  }

  for(i=0;i<(int)v3.size();i++){

    if(i+1==(int)v3.size())continue;

    v3[i+1]+=v3[i];

  }

  for(i=0;i<(int)v4.size();i++){

    if(i+1==(int)v4.size())continue;

    v4[i+1]+=v4[i];

  }

  v1.insert(v1.begin(), 0);

  v2.insert(v2.begin(), 0);

  v3.insert(v3.begin(), 0);

  v4.insert(v4.begin(), 0);



  REP(i, (int)v1.size()){

    REP(j, (int)v2.size()){

      REP(k, (int)v3.size()){

        REP(l, (int)v4.size()){

          if(i*w[0]+j*(w[0]+1)+k*(w[0]+2)+l*(w[0]+3) <= W){

            sm = max(sm, v1[i]+v2[j]+v3[k]+v4[l]);

          }

        }

      }

    }

  }

  cout << sm << endl;

  return 0;

}


// Optimized solution to the same problem (faster):
#include<cstdio>



#include<cstring>

#include<algorithm>

#define ll long long

#define MAXN 100000005



using namespace std;







struct TH{

	ll w,v;

}th[105];



ll v1[105],v2[105],v3[105],v4[105];



int cnt1=0,cnt2=0,cnt3=0,cnt4=0; 



bool cmp(ll a,ll b){

	return a>b;

}



int main(){

	ll n,w;

	scanf("%lld %lld",&n,&w);

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

		scanf("%lld %lld",&th[i].w,&th[i].v);

		if(i==1){

			v1[++cnt1]=th[i].v;

			continue;

		}

		//以w[1]为基准， 把所有价值分为4类 

		int con=th[i].w-th[1].w;

		switch(con){//从1开始存放 

			case 0:v1[++cnt1]=th[i].v;break;

			case 1:v2[++cnt2]=th[i].v;break;

			case 2:v3[++cnt3]=th[i].v;break;

			case 3:v4[++cnt4]=th[i].v;break;

		}

	}

	//所有价值从大到小排序 

	sort(v1+1,v1+cnt1+1,cmp);

	sort(v2+1,v2+cnt2+1,cmp);

	sort(v3+1,v3+cnt3+1,cmp);

	sort(v4+1,v4+cnt4+1,cmp);

	//每种类型的物品价值叠加 

	for(int i=2;i<=cnt1;i++){

		v1[i]+=v1[i-1];

	} 

	for(int i=2;i<=cnt2;i++){

		v2[i]+=v2[i-1];

	} 

	for(int i=2;i<=cnt3;i++){

		v3[i]+=v3[i-1];

	} 

	for(int i=2;i<=cnt4;i++){

		v4[i]+=v4[i-1];

	} 

	ll ans=0;

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

		for(int j=0;j<=cnt2;j++){

			for(int k=0;k<=cnt3;k++){

				for(int h=0;h<=cnt4;h++){

					if(th[1].w*(i)+(th[1].w+1)*(j)+(th[1].w+2)*(k)+(th[1].w+3)*(h)<=w){

						ans=max(ans,v1[i]+v2[j]+v3[k]+v4[h]);

					}

				}

			}

		}

	}

	printf("%lld",ans);

	return 0;

} 

// Fastest known solution for this problem: