#include <iostream>
#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
struct data
{
int W, V;
} typedef data;
int N;
int M;
data Gold1 [45];
data Gold2 [45];
int SMax;
int S[1300006];
int cmp (data a, data b)
{
if (a.W>=b.W) return 0;
return 1;
}
vector <data> P1;
vector <data> P2;
int N1, N2;
data tmp;
void sinh1 (int u, int W, int V)
{
if (W>M) return;
if (u==N1+1)
{
tmp.W=W;
tmp.V=V;
P1.push_back (tmp);
return;
}
else
{
sinh1 (u+1, W, V);
sinh1 (u+1, W+Gold1[u].W, V+Gold1[u].V);
}
}
void sinh2 (int u, int W, int V)
{
if (W>M) return;
if (u==N2+1)
{
tmp.W=W;
tmp.V=V;
P2.push_back (tmp);
return;
}
else
{
sinh2 (u+1, W, V);
sinh2 (u+1, W+Gold2[u].W, V+Gold2[u].V);
}
}
int BS (int front, int back, int x)
{
int vt=-1;
while (front<=back)
{
int mid = (front+back)/2;
if (P2[mid].W<=x)
{
front=mid+1;
vt=mid;
} else back=mid-1;
}
return vt;
}
int main ()
{
scanf ("%d%d", &N, &M);
N2=N/2;
N1=N-(N/2);
for (int i=1; i<=N1; i++)
{
scanf ("%d%d", &Gold1[i].W, &Gold1[i].V);
}
for (int i=1; i<=N2; i++)
{
scanf ("%d%d", &Gold2[i].W, &Gold2[i].V);
}
//Tim truong hop:
sinh1 (1, 0, 0);
sinh2 (1, 0, 0);
sort (P2.begin(), P2.end(), cmp);
int Ans=0;
S[0]=P2[0].V;
for (int i=1; i<P2.size(); i++)
{
S[i]=max (S[i-1], P2[i].V);
Ans = max (Ans, P2[i].V);
}
for (int i=0; i<P1.size (); i++)
{
int VT = BS (0, P2.size()-1, M-P1[i].W);
if (VT!=-1)
{
Ans = max (Ans, S[VT]+P1[i].V);
}
Ans = max (Ans, P1[i].V);
}
printf ("%d", Ans);
return 0;
}