//http://abc060.contest.atcoder.jp/tasks/arc073_b
//
//  main.c
//  abc060_d
//
//  Created by Ding Chao on 4/29/17.
//  Copyright © 2017 Ding Chao. All rights reserved.
//
#define DBq
#include <stdio.h>
#include <stdlib.h>
int compare_function(const void *a,const void *b) {
    long long *x = (long long *) a;
    long long *y = (long long *) b;
    if (*x > *y)
        return -1;
    if (*x == *y)
        return 0;
    return 1;
}

int main2(int w[], int v[], int n, int wmax);

long long max(long long a, long long b) {
    return a > b ? a : b;
}

long long min(long long a, long long b) {
    return a < b ? a : b;
}

void sort(long long arr[], int len) {
//    //insertion sort
//    for (int i = 1; i < len; i++) {
//        // 0 to i - 1 is sorted
//        for (int j = i; j > 0; j--) {
//            //try to find the place of j so that 0 to i is sorted. 
//            if (arr[j] > arr[j - 1]) {
//                //move j one step forward
//                long long t = arr[j];
//                arr[j] = arr[j - 1];
//                arr[j - 1] = t;
//            }
//            else
//                break; //ordered. 
//        }
//    }
    qsort(arr, len, sizeof(long long), compare_function);
}

void printArr(long long arr[], int len) {
#ifdef DB
    for (int i = 0; i < len; i++)
        printf("%lld ", arr[i]);
    printf("\n");
#endif
}

int main1(int seed) {
//    long long arr[10] = {-1, 8, 6, 7, 5, 4, 3, 2, 0, 1};
//    sort(arr, 10);
//    printArr(arr, 10);
#ifdef DB
    freopen("/Users/DC/ownCloud/CodingContests/AtCoder/abc060/abc060_d/abc060_d/input.txt", "r", stdin);
#endif
    int N, W, w[100], v[100];
    scanf("%d%d", &N, &W);
#ifdef DB
    srand(seed);
    N = rand() % 100 + 1; W = 1000000000;
#endif
    for (int i = 0; i < N; i++) {
        scanf("%d%d", &w[i], &v[i]);
    }
#ifdef DB
//    w[0] = W / 2;
    w[0] = rand() % W;
#endif
    int w1 = w[0];
#ifdef DB
    for (int i = 1; i < N; i++) {
//        do {
            w[i] = w1 + rand() % 4;
//        }while(w[i] == w1 + 2 || w[i] == w1 + 3);
        v[i] = rand() / 10000000;
    }
#endif
//    w[0] -= 3;
//    v[9] = 100 * v[9];
    
    //values[i][j] is the jth value of them of weight w1 + i
    long long values[4][100]; 
    int valuesLen[4] = {0, 0 ,0 ,0};
    for (int i = 0; i < N; i++) {
        int w_index = w[i] - w1;
        values[w_index][valuesLen[w_index]] = v[i];
        valuesLen[w_index]++;
    }
    
    for (int i = 0; i < 4; i++) {
        sort(values[i], valuesLen[i]);
        printArr(values[i], valuesLen[i]);
    }
    
    //maxValue of weight i and j items. 
    long long valueSum[4][101];//0 to 100 items. 
    
#ifdef DB
    printf("Printing valueSum. \n");
#endif
    for (int i = 0; i < 4; i++) {
        valueSum[i][0] = 0;
        for (int j = 1; j <= valuesLen[i]; j++) {
            valueSum[i][j] = valueSum[i][j - 1] + values[i][j - 1];
        }
        printArr(valueSum[i], valuesLen[i] + 1);
    }
    
    long long result = 0;
    
    for (long long k0 = 0; k0 <= valuesLen[0] && k0 * w1 <= W; k0++) {
        for (long long k1 = 0; k1 <= valuesLen[1]; k1++) {
            for (long long k2 = 0; k2 <= valuesLen[2]; k2++) {
                long long cost = (k2 * (w1 + 2) + k1 * (w1 + 1) + k0 * w1); 
                long long remain = W - cost;
                if (remain >= 0) {
                    int k3 = min(remain / (w1 + 3), valuesLen[3]);
                    long long newResult = valueSum[0][k0] + valueSum[1][k1] 
                        + valueSum[2][k2] + valueSum[3][k3];
                    result = max(result, newResult);
                    if (result == 1417) {
                        
                    }
                }
            }
        }
    }

        
    printf("%lld\n", result);
    
#ifdef DB
    printf("Run an AC code. \n");
    int result2 = main2(w, v, N, W);
    if (result2 != result)
        printf("Not Equal!\nThe seed is %d. \n", seed);
#endif
    return 0;
}

struct ar {
    struct slot {
        int w, v;
    } slot[40001];
} ar[2];
int add(struct ar *old, int w, int v, int wmax, struct ar *new)
{
    struct slot *oldp = old->slot;
    struct slot *addp = old->slot;
    struct slot *newp = new->slot;
    int current_maxv = -1;
    for (;;) {
        if (oldp->w >= 0) {
            if (addp->w >= 0) {
                int addpw = addp->w + w;
                int addpv = addp->v + v;
                if (oldp->w < addpw)
                    goto putoldp;
                else if (oldp->w > addpw)
                    goto putaddp;
                else {
                    if (oldp->v < addpv) {
                        oldp++;
                        goto putaddp;
                    } else {
                        addp++;
                        goto putoldp;
                    }
                }
            } else
                goto putoldp;
        } else {
            if (addp->w >= 0)
                goto putaddp;
            else
                break;
        }
    putoldp:
        if (current_maxv < oldp->v) {
            *newp++ = *oldp;
            current_maxv = oldp->v;
        }
        oldp++;
        continue;
    putaddp:
        {
            int addpw = addp->w + w;
            int addpv = addp->v + v;
            if (wmax < addpw)
                break;
            if (current_maxv < addpv) {
                newp->v = addpv;
                newp->w = addpw;
                current_maxv = addpv;
                newp++;
            }
            addp++;
            continue;
        }
    }
    newp->w = -1;
    newp->v = -1;
    return current_maxv;
}

int main2(int w[], int v[], int n, int wmax) {
    struct ar *old = &ar[0];
    struct ar *new = &ar[1];
    old->slot[0].w = 0;
    old->slot[0].v = 0;
    old->slot[1].w = -1;
    
    int vmax = -1;
    int i;
    for (i = 0; i < n; ++i) {
        int wi, vi;
//        scanf("%d%d", &wi, &vi);
        wi = w[i];
        vi = v[i];
        vmax = add(old, wi, vi, wmax, new);
        struct ar *tmp = new;
        new = old;
        old = tmp;
    }
    printf("%d\n", vmax);
    return vmax;
}
#include <limits.h>
int main() {
    int r = -1;
    r = main1(2);
#ifdef DB
    for (int seed = 1; seed < INT_MAX; seed++) {
        r = main1(seed);
    }
#endif
    
    return r;
}

Measured memory_bytes: 128