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

using namespace std;



int main() {

    ios::sync_with_stdio(false);

    int N, W;

    cin >> N >> W;

    int w[N + 1], v[N + 1];

    map<int, vector<int> > dict;

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

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

        dict[w[i]].push_back(v[i]);

    }

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

        vector<int>& v = dict[w[1] + i];

        sort(v.begin(), v.end(), greater<int>());                           // descending order

    }

    int max_value = 0;

    for (int a = 0; (size_t)a <= dict[w[1]].size(); a++) {                  // 'a': qty of w1

        if (a * w[1] > W)

            break;

        int value_a = 0;

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

            value_a += dict[w[1]][i];

        for (int b = 0; (size_t)b <= dict[w[1] + 1].size(); b++) {          // 'b': qty of w1+1

            if (a * w[1] + b * (w[1] + 1) > W)

                break;

            int value_b = 0;

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

                value_b += dict[w[1] + 1][i];

            for (int c = 0; (size_t)c <= dict[w[1] + 2].size(); c++) {      // 'c': qty of w1+2

                if (a * w[1] + b * (w[1] + 1) + c * (w[1] + 2) > W)

                    break;

                int value_c = 0;

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

                    value_c += dict[w[1] + 2][i];

                for (int d = 0; (size_t)d <= dict[w[1] + 3].size(); d++) {  // 'd': qty of w1+3

                    if (a * w[1] + b * (w[1] + 1) + c * (w[1] + 2) + d * (w[1] + 3) > W)

                        break;

                    int value_d = 0;

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

                        value_d += dict[w[1] + 3][i];

                    max_value = max(max_value, value_a + value_b + value_c + value_d);

                }

            }

        }

    }

    cout << max_value << "\n";



    return 0;

}

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

#include <cstring>

#include <cmath>

#include <algorithm>

using namespace std;

typedef long long LL;

struct huowu

{

	int w,v;

}g[105];

huowu A[105], B[105], C[105], D[105];

bool cmp(huowu a,huowu b)

{

	return a.v > b.v;

}

int n,W;

int main()

{

	scanf("%d %d",&n,&W);

	int a, b, c, d, f;

	a = b = c = d = f = 0;

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

	{

		scanf("%d %d",&g[i].w,&g[i].v);

		if(g[i].w == g[1].w)

		{

			A[++a] = g[i];

		}

		else if(g[i].w == g[1].w + 1)

		{

			B[++b] = g[i];

		}

		else if(g[i].w == g[1].w + 2)

		{

			C[++c] = g[i];

		}

		else if(g[i].w == g[1].w + 3)

		{

			D[++d] = g[i];

		}

	}

	sort(A + 1,A + 1 + a,cmp);

	sort(B + 1,B + 1 + b,cmp);

	sort(C + 1,C + 1 + c,cmp);

	sort(D + 1,D + 1 + d,cmp);

	LL swa[110],swb[110],swc[110],swd[110];

	LL sva[110],svb[110],svc[110],svd[110];

	swa[0] = swb[0] = swc[0] = swd[0] = 0;  

    sva[0] = svb[0] = svc[0] = svd[0] = 0;  

    for(int i = 1;i <= a;i++)  

    {  

        swa[i] = swa[i - 1] + A[i].w;  

        sva[i] = sva[i - 1] + A[i].v;  

    }  

    for(int i = 1;i <= b;i++)  

    {  

        swb[i] = swb[i - 1] + B[i].w;  

        svb[i] = svb[i - 1] + B[i].v;  

     }  

     for(int i = 1;i <= c;i++)  

     {  

         swc[i] = swc[i - 1] + C[i].w;  

         svc[i] = svc[i - 1] + C[i].v;  

     }  

     for(int i = 1;i <= d;i++)  

     {  

        swd[i] = swd[i - 1] + D[i].w;  

        svd[i] = svd[i - 1] + D[i].v;  

      }  

    int sumv = 0;  

    int ans = 0;  

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

    {  

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

         {  

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

            {  

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

              {  

			      LL sum = swa[i] + swb[j] + swc[k] + swd[l];  

					if(sum <= (LL)W)  

					{  

                      f = max((LL)f,sva[i] + svb[j] + svc[k] + svd[l]);  

					}  

			 }  

            }  

        }  

    }  

    printf("%d\n",f); 

    return 0;  

}  

	

	

// Fastest known solution for this problem: