/* Aditya0412 */
#include <bits/stdc++.h>
using namespace std; 
#define int long long 
#define pb push_back 
#define vii vector < int > 
#define pii pair < int , int >
#define fi first
#define all(a)      (a).begin(),(a).end()
#define si(x)       (int)((x).size())
#define debug(x)    cout<<#x<<" is "<<(x)<<endl;cout.flush();  
#define se second 
#define endl        '\n'
#define f(i,a,b)    for(int i=a;i<b;i++)
#define mem(a,x)          memset(a,x,sizeof(a))
#define fastIO ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
const int  mod=998244353;
// const int  mod = 1000000000+7;
const int  N=1000000+6;
#define M_PI           3.14159265358979323846
// In C++, comparator should return false if its arguments are equal.
// === Debug macro starts here ===
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os,  const Cont& v){
    os<<"[";
    for(auto& x:v){os<<x<<", ";}
    return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os,  const pair<Ts...>& p){
    return os<<"{"<<p.first<<", "<<p.second<<"}";
}
// === Debug macro ends here ===
int inv[3000000+5],fac_inv[3000000+5],fac[3000000+5];
void initialize()
{
	int i;
	inv[1]=1;
	for(i=2;i<=3000000;i++)
		inv[i]=(mod-mod/i)*inv[mod%i]%mod; 
	fac[0]=fac[1]=1;
	for(i=2;i<=3000000;i++)
		fac[i]=i*fac[i-1]%mod;
	fac_inv[0]=fac_inv[1]=1;
	for(i=2;i<=3000000;i++)
		fac_inv[i]=inv[i]*fac_inv[i-1]%mod;
}

int ncr(int n,int r)
{
	if(n<r) return 0;
	return (fac[n]*fac_inv[r]%mod)*fac_inv[n-r]%mod;
}
int spf[N];
void smallest_prime()
{
    mem(spf,0);
    for(int i=2;i<N;i++)
    {
        if(spf[i]==0)
        {
            spf[i]=i;
            for(int j=i*i;j<N;j+=i)
            if(spf[j]==0)
            spf[j]=i;
        }
    }
   
}
int n,m;
int32_t main() 
{
	// _ _| | _ _ _
    fastIO;smallest_prime();initialize();
  	cin>>n>>m;int ans=0;
  	for(int i=1;i<=m;i++){
  		int t=1;
  		int x=i;
  		while(x!=1)
  		{
  			int y=spf[x],z=0;
  			while(x%y==0)
  			{
  				x/=y;z++;
  			}
  			t*=ncr(z+n-1,n-1);
  			t%=mod;
  		}
  		ans+=t;ans%=mod;
  	}
  	cout<<ans;

} 
#include<iostream>
#include<string>
#include<algorithm>    
#include<cmath>
#include<map>
#include<vector>
#include<math.h>
#include<stdio.h>
#include<stack>
#include<queue>
#include<tuple>
#include<cassert>
#include<set>
#include<functional>
//#include<bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i, x) for(ll i = 0; i < x; i++)
#define rep2(i, x) for(ll i = 1; i <= x; i++)
#define all(a) (a).begin(),(a).end()
using ll = long long;
using ld = long double;
using namespace std;
const ll INF = 10000000000000000;
const int intINF = 1000000000;
const ll mod = 1000000007;
const ll MOD = 998244353;
const ld pi = 3.141592653589793238;

bool isprime(int p) {
	if (p == 1) return false;
	for (int i = 2; i < p; i++) {
		if (p % i == 0) return false;
	}
	return true;
}
ll gcd(ll a, ll b) {
	if (a < b)swap(a, b);
	if (a % b == 0)return b;
	return gcd(b, a % b);
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
ll keta(ll n) {
	ll res = 0;
	while (n >= 1) {
		res += n % 10; n /= 10;
	}
	return res;
}
ll modpow(ll x, ll y) {
	ll res = 1;
	while (y) {
		if (y % 2) { res *= x; res %= mod; }
		x = x * x % mod; y /= 2;
	}
	return res;
}
ll nCk(ll n, ll k) {
	ll a = 1, b = 1;
	for (int h = n - k + 1; h <= n; h++) { a *= h; a %= mod; }
	for (int h = 1; h <= k; h++) { b *= h; b %= mod; }
	return a * modpow(b, mod - 2) % mod;
}
//printf("%.10f\n", n);
typedef pair <ll, ll> P;
ll dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, 1, 0, -1 };
struct edge { ll to, cost; };
struct status {
	ll y;
	ll high;
	ll cost;

	bool operator<(const status& rhs) const { return cost < rhs.cost; };
	bool operator>(const status& rhs) const { return cost > rhs.cost; };
};

ll a[123456], w1[1234567], w2[1234567];
signed main() {
	ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	//cout << fixed << setprecision(15);


	ll n, x; cin >> n >> x;
	rep(i, n) {
		cin >> a[i];
	}
	for (int i = 0; i < (1 << (n / 2)); i++) {
		ll sum = 0;
		for (int j = 0; j < (n / 2); j++) {
			if ((i / (1 << j)) % 2 == 0) sum += a[j];
		}
		w1[i] = sum;
	}

	// 後半 N - N/2 個を bit 全探索で全列挙する
	for (int i = 0; i < (1 << (n - (n / 2))); i++) {
		ll sum = 0;
		for (int j = 0; j < n - (n / 2); j++) {
			if ((i / (1 << j)) % 2 == 0) sum += a[j + (n / 2)];
		}
		w2[i] = sum;
	}

	// ソートしたうえで半分全列挙をする
	ll ans = 0;
	sort(w1, w1 + (1 << (n / 2)));
	sort(w2, w2 + (1 << (n - (n / 2))));
	for (int i = 0; i < (1 << (n / 2)); i++) {
		ll rem = x - w1[i];
		ll pos1 = upper_bound(w2, w2 + (1 << (n - (n / 2))), rem) - w2;
		if (pos1 == 0) { continue; }
		pos1--;
		ans = max(ans, w1[i] + w2[pos1]);
	}
	cout << ans << endl;
	return 0;
}