#include <stdio.h>
#include <stdlib.h>

#define ARR_SIZE 2001
#define TRUE    1
#define FALSE   0

int n, W;
int p[ARR_SIZE];
int w[ARR_SIZE];
int include[ARR_SIZE];
int bestSet[ARR_SIZE];
int numbSet;
int maxProfit;

struct Item {
    double pr;
    int index;
};

struct Item temp[ARR_SIZE];


void input();
void output();
void knapsack(int i, int profit, int weight);
int promising(int i, int profit, int weight);

int compare(const void *A, const void *B) {
    struct Item *ptrA = (struct Item*)A;
    struct Item *ptrB = (struct Item*)B;
    
    if(ptrA->pr < ptrB->pr) return 1;
    else if(ptrA->pr == ptrB->pr) return 0;
    else return -1;
}


int main(void) {
    input();
    knapsack(0, 0, 0);
    output();
    
    return 0;
}

void input() {
    int i;
    
    int tp[ARR_SIZE];
    int tw[ARR_SIZE];
    
    scanf("%d %d", &n, &W);
    
//    for(i=1; i<=n; i++)
//        scanf("%d %d", &w[i], &p[i]);
    
    temp[0].pr = 99999999;
    
    for(i=1; i<=n; i++) {
        scanf("%d %d", &tp[i], &tw[i]);
        temp[i].index = i;
        temp[i].pr = ((double)tp[i] / tw[i]);
    }
    
    qsort(temp, n+1, sizeof(struct Item), compare);
    
    for(i=1; i<=n; i++) {
        p[i] = tp[temp[i].index];
        w[i] = tw[temp[i].index];
    }
    
}

void output() {
    int i;
    
    printf("%d\n", maxProfit);
    
//    for(i=1; i<=n; i++)
//        printf("%d\n", bestSet[i]);
}

void knapsack(int i, int profit, int weight) {
    int j;
    
    if(weight <= W && profit > maxProfit) {
        maxProfit = profit;
        numbSet = i;
        
        for(j=0; j<=n; j++)
            bestSet[j] = include[j];
    }
    
    if(promising(i, profit, weight)) {
        include[i + 1] = 1;
        knapsack(i+1, profit + p[i+1], weight + w[i+1]);
        include[i + 1] = 0;
        knapsack(i+1, profit, weight);
    }
}

int promising(int i, int profit, int weight) {
    int j, k;
    int totalWeight;
    double bound;
    
    if(weight >= W) {
        return FALSE;
    } else {
        j = i + 1;
        bound = (double)profit;
        totalWeight = weight;
        
        while(j <= n && totalWeight + w[j] <= W) {
            totalWeight += w[j];
            bound += p[j];
            j++;
        }
        
        k = j;
        
        if(k <= n)
            bound = bound + (W - totalWeight) * (p[k] / w[k]);
        
        if(bound > maxProfit)
            return TRUE;
        else
            return FALSE;
    }
}