#include <bits/stdc++.h>

/* snippet: useful macros and functions */
#define ARC(i, a, b) for(Int i = (a); i < (b); ++i)
#define RC(i, n) ARC(i, 0, n)
#define ARCH(i, a, b) for(Int i = (a) - 1; i >= (b); --i)
#define RCH(i, n) ARCH(i, n, 0)
#define ALL(v) v.begin(), v.end()
template<class T> T rng(const T &a, const T &b){ return a < b ? b - a : a - b; }
template<class T> void chmaxmin(T &a, const T &b, const T &(*f)(const T &, const T &)){ a = f(a, b); }
#define chmax(a, b) chmaxmin(a, b, std::max)
#define chmin(a, b) chmaxmin(a, b, std::min)

#if __has_include(<experimental/iterator>)
#include <experimental/iterator>
auto debug = std::experimental::make_ostream_joiner(std::cout, " ");
#endif

/* snippet: inf struct */
#if __cplusplus >= 201703
struct{ template<class T> constexpr operator T(){ return std::numeric_limits<T>::max(); } constexpr auto operator-(); } inf;
struct{ template<class T> constexpr operator T(){ return std::numeric_limits<T>::lowest(); } constexpr auto operator-(); } negative_inf;
constexpr auto decltype(inf)::operator-(){ return negative_inf; }
constexpr auto decltype(negative_inf)::operator-(){ return inf; }
#endif

/* snippet: modint library */
#if __cpp_concepts
template<std::signed_integral T, T MOD>
#else
template<class T, T MOD>
#endif
class Modint{
	T val;
public:
	Modint(T val = 0) : val(val % MOD + (val >= 0 ? 0 : MOD)) {}
	operator T(){ return val; }
	Modint &operator+=(const Modint &a){ val += a.val; if(val >= MOD) val -= MOD; return *this; }
	Modint &operator-=(const Modint &a){ val -= a.val; if(val < 0) val += MOD; return *this; }
	Modint &operator*=(const Modint &a){ val = val * a.val % MOD; return *this; }
	void inverse(){T x[2]={MOD,val},a[2]={0,1};int i;for(i=0;x[!i];i^=1){a[i]-=x[i]/x[!i]*a[!i];x[i]=x[i]%x[!i];}if(!i)a[i]+= MOD;val=a[i];}
	Modint &operator/=(Modint a){ a.inverse(); return *this *= a; }
	friend Modint modpow(Modint a, int n){ Modint ret(1); while(n){ if(n & 1) ret *= a; a *= a; n >>= 1; } return ret; }
	friend Modint operator+(Modint a, const Modint &b){ return a += b; }
	friend Modint operator-(Modint a, const Modint &b){ return a -= b; }
	friend Modint operator*(Modint a, const Modint &b){ return a *= b; }
	friend Modint operator/(Modint a, const Modint &b){ return a /= b; }
	friend std::ostream &operator<<(std::ostream &os, const Modint &a){ return os << a.val; }
};

/* push n numbers and get i-th min */
/* to get min and 2nd min, declare K_th_min<T, 2> and use get<0>(), get<1>() */
#if __cplusplus >= 201703
template<class T, std::size_t K>
class K_th_min{
	friend class K_th_min<T, K + 1>;
	T val;
	K_th_min<T, K - 1> lower;
	void push_(T &x){ lower.push_(x); if(val > x) std::swap(val, x); }
public:
	K_th_min() : val(std::numeric_limits<T>::max()) {}
	void push(T x){ push_(x); }
	template<std::size_t I> T get(){ if constexpr(I == K - 1) return val; else return lower.template get<I>(); }
};
template<class T> class K_th_min<T, 0>{ friend class K_th_min<T, 1>; void push_(T &){} public: K_th_min(){} void push(T){} };
#endif

/* snippet: using declarations */
using Int = long long;
using std::cout;
using std::cin;
using std::endl;
using Mint = Modint<long long, 998244353>;

using Real = double;
using Complex = std::complex<Real>;

template<int M, int N>
constexpr Complex zeta(){
	return Complex(cos(2 * M_PI * N / M), sin(2 * M_PI * N / M));
}

template<int N, int SIGN, int I = 0>
struct array_mulzeta{
	static void mulzeta(Complex x[]){
		*x *= zeta<N * 2, SIGN * I>();
		array_mulzeta<N, SIGN, I + 1>::mulzeta(x + 1);
	}
};
template<int N, int SIGN>
struct array_mulzeta<N, SIGN, N>{
	static void mulzeta(Complex []){}
};
template<int SIZE, int I = 0>
struct array{
	static void add(Complex a[], Complex b[], Complex c[]){
		*c = *a + *b;
		array<SIZE, I + 1>::add(a + 1, b + 1, c + 1);
	}
	static void subst(Complex a[], Complex b[], Complex c[]){
		*c = *a - *b;
		array<SIZE, I + 1>::subst(a + 1, b + 1, c + 1);
	}
	static void div(Complex x[]){
		*x /= SIZE;
		array<SIZE, I + 1>::div(x + 1);
	}
};
template<int SIZE>
struct array<SIZE, SIZE>{
	static void add(Complex [], Complex [], Complex []){}
	static void subst(Complex [], Complex [], Complex []){}
	static void div(Complex []){};
};

template<int SIZE, int SIGN, int GAP = 1>
struct array_FFT{
	static void FFT(const Complex x[], Complex X[]){
		Complex even[SIZE / 2], odd[SIZE / 2];
		array_FFT<SIZE / 2, SIGN, GAP * 2>::FFT(x, even);
		array_FFT<SIZE / 2, SIGN, GAP * 2>::FFT(x + GAP, odd);
		array_mulzeta<SIZE / 2, SIGN>::mulzeta(odd);
		array<SIZE / 2>::add(even, odd, X);
		array<SIZE / 2>::subst(even, odd, X + SIZE / 2);
	}
};
template<int SIGN, int GAP>
struct array_FFT<1, SIGN, GAP>{
	static void FFT(const Complex x[], Complex X[]){
		*X = *x;
	}
};

template<int N>
void DFT(const Complex (&x)[N], Complex X[]){
	array_FFT<N, 1>::FFT(x, X);
}
template<int N>
void IDFT(const Complex (&X)[N], Complex x[]){
	array_FFT<N, -1>::FFT(X, x);
	array<N>::div(x);
}

int main(){
	Int n, s;
	cin >> n >> s;

	std::vector<Int> a(n);
	RC(i, n){
		cin >> a[i];
	}

	static Mint dp[3123];
	RC(i, s + 1){
		dp[i] = 0;
	}
	dp[0] = modpow(Mint(2), n);
	RC(i, n){
		for(Int j = s - a[i]; j >= 0; --j){
			dp[j + a[i]] += dp[j] / Mint(2);
		}
		//RC(j, s + 1) cout << dp[j] << " ";
		//cout << endl;
	}
	cout << dp[s] << endl;

	/*
	static Int dp[3123][3123] = {};

	dp[0][0] = 1;

	RC(i, n){
		RCH(j, n){
			RCH(k, s - a[i] + 1){
				dp[j + 1][k + a[i]] += dp[j][k];
			}
		}
		RC(j, n){
			RC(k, s + 1){
				cout << dp[j][k] << " ";
			}
			cout << endl;
		}
		cout << endl;
	}

	Mint ans = 0;
	RC(i, n){
		ans += modpow(Mint(2), n - i) * Mint(dp[i][s]);
	}
	cout << ans << endl;
	*/
}


Measured memory_bytes: 3656