#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <stack>
#include <list>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#include <cmath>
#include <climits>
#include <map>
#include <unordered_map>
#include <string.h>
#include<iomanip>
#include <iterator>
#include <locale>

#define all(a) a.begin(),a.end()
#define VV(T) vector<vector< T > >
#define rep(i,N) for(int i = 0; i <N; i++)
#define repsg(i,s,g) for(int i = s; i <g; i++)
#define name(x) #x
using namespace std;


const int INF = 10000000;
const long long INFL = (1LL<<50);
const double PI = atan(1)*4;
const int MOD = pow(10,9)+7;
int dy[]={0, 0, 1, -1, 0};
int dx[]={1, -1, 0, 0, 0};

typedef long long ll,LL;
typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll, vLL;
typedef vector<vector<long long> > vvll, vvLL;
typedef pair<int,int> pii;
typedef pair<LL, LL> pLL;


// vector入力
template<typename T>
istream& operator >> (istream& is, vector<T>& vec){
    for(T& x: vec) is >> x;
    return is;
}
// vector出力
template<typename T>
ostream& operator << (ostream& os, vector<T>& vec){
    for(int i=0; i<vec.size(); i++){
        os << vec[i] << ( i+1 == vec.size() ? "" : " " );
    }
    return os;
}


int main() {
    ll N,W;cin>>N>>W;
    vector<vector<ll>> val(4);
    ll w,v;
    cin>>w>>v;
    ll minW = w;
    val[0].push_back(v);
    for(auto i = 1; i<N;i++){
        cin>>w>>v;
        val[w-minW].push_back(v);
    }
    rep(i,4){
        sort(all(val[i]),greater<ll>());
    }
    ll maxval = 0;
    ll n = W/(minW+3);
    rep(m1,n+1){
        rep(m2,n+1){
            rep(m3,n+1){
        ll m4 = n - m1 - m2 - m3;
        if(m1 >val[0].size() || m2 >val[1].size()||m3 >val[2].size()||m4 >val[3].size()) continue;
        if(m4 < 0) continue;
        if (minW*m1 + (minW+1)*m2+ (minW+2)*m3+ (minW+3)*m4 >W) continue;
        ll sum = 0;
        rep(i,m1) sum+=val[0][i];
        rep(i,m2) sum+=val[1][i];
        rep(i,m3) sum+=val[2][i];
        rep(i,m4) sum+=val[3][i];
        maxval = max(maxval,sum);
    }}}
    n++;
    rep(m1,n+1){rep(m2,n+1){rep(m3,n+1){
        ll m4 = n - m1 - m2 - m3;
        if(m1 >val[0].size() || m2 >val[1].size()||m3 >val[2].size()||m4 >val[3].size()) continue;
        if(m4 < 0) continue;
        if (minW*m1 + (minW+1)*m2+ (minW+2)*m3+ (minW+3)*m4 >W) continue;
        ll sum = 0;
        rep(i,m1) sum+=val[0][i];
        rep(i,m2) sum+=val[1][i];
        rep(i,m3) sum+=val[2][i];
        rep(i,m4) sum+=val[3][i];
        maxval = max(maxval,sum);
    }}}
    n++;
    rep(m1,n+1){rep(m2,n+1){rep(m3,n+1){
        ll m4 = n - m1 - m2 - m3;
        if(m1 >val[0].size() || m2 >val[1].size()||m3 >val[2].size()||m4 >val[3].size()) continue;
        if(m4 < 0) continue;
        if (minW*m1 + (minW+1)*m2+ (minW+2)*m3+ (minW+3)*m4 >W) continue;
        ll sum = 0;
        rep(i,m1) sum+=val[0][i];
        rep(i,m2) sum+=val[1][i];
        rep(i,m3) sum+=val[2][i];
        rep(i,m4) sum+=val[3][i];
        maxval = max(maxval,sum);
    }}}
    n++;
    rep(m1,n+1){rep(m2,n+1){rep(m3,n+1){
        ll m4 = n - m1 - m2 - m3;
        if(m1 >val[0].size() || m2 >val[1].size()||m3 >val[2].size()||m4 >val[3].size()) continue;
        if(m4 < 0) continue;
        if (minW*m1 + (minW+1)*m2+ (minW+2)*m3+ (minW+3)*m4 >W) continue;
        ll sum = 0;
        rep(i,m1) sum+=val[0][i];
        rep(i,m2) sum+=val[1][i];
        rep(i,m3) sum+=val[2][i];
        rep(i,m4) sum+=val[3][i];
        maxval = max(maxval,sum);
    }}}
    cout<<maxval<<endl;
    
    return 0;
}












Measured memory_bytes: 256