#include <bits/stdc++.h>
using namespace std;

#if 1 // 折り畳み用
//------------------------------------------------------------
using ll = long long;
#define int ll

#define FOR(i, s, e) for (ll i = ll(s); i < (ll)e; ++i)
#define RFOR(i, s, e) for (ll i = ll(e) - 1; i >= ll(s); --i)
#define REP(i, n) for (ll i = 0, i##_size = n; i < i##_size; ++i)
#define RREP(i, n) for (ll i = ll(n) - 1; i >= 0; --i)

//------------------------------------------------------------
template <class T>
struct arr : public vector<T> {
	arr() {}
	arr(ll n, T v = T()) : vector<T>(n, v) {}
	void init(ll n, T v = T()) {
		this->clear();
		this->resize(n, v);
	}
	ll sz() const { return (ll)this->size(); }
	void pb(T v) { this->push_back(v); }
	void sort() { std::sort(this->begin(), this->end()); }
	void rsort() { std::sort(this->begin(), this->end(), greater<T>()); }
};
using ints = arr<ll>;
using intss = arr<arr<ll>>;

template <class T>
struct que : public queue<T> {
	ll sz() const { return (ll)this->size(); }
	T popfront() {
		T v = this->front();
		this->pop();
		return v;
	}
};

//------------------------------------------------------------
#if defined(TEST)
extern istream& myInputStream;
extern ostream& myOutputStream;
#else
istream& myInputStream = cin;
ostream& myOutputStream = cout;
#endif
struct input_ar {
	ll n;
	input_ar(ll n_) : n(n_) {}
	template <class T>
	operator arr<T>() {
		arr<T> var(n);
		REP(i, n) {
			myInputStream >> var[i];
		};
		return var;
	}
};

struct input {
	template <class T>
	operator T() {
		T var;
		myInputStream >> var;
		return var;
	}
	input_ar operator()(ll N) { return input_ar(N); }
} input;

template <class T>
void output(T var) {
	myOutputStream << (var) << '\n';
}

//------------------------------------------------------------
template <class T> void chmin(T& a, T b) { if (b < a) { a = b; } }
template <class T> void chmax(T& a, T b) { if (b > a) { a = b; } }

//------------------------------------------------------------
struct bfs {
	ints froms;
	ints steps;

	bfs(int N, intss const& adjacency) {
		froms.init(N, -1);
		steps.init(N, -1);

		que<ll> queue;
		queue.push(0);
		froms[0] = 0;
		steps[0] = 0;

		while (queue.empty() == false) {
			ll p = queue.popfront();

			for (ll n : adjacency[p]) {
				if (froms[n] != -1) {
					continue;
				}

				froms[n] = p;
				steps[n] = steps[p] + 1;
				queue.push(n);
			}
		}
	}
};

//------------------------------------------------------------
template <int MOD>
struct modint {
	int raw;

	modint(int v = 0) {
		raw = v;
		if (raw >= MOD) { raw %= MOD; }
	}
	modint operator + (modint v) const {
		return modint(raw) += v;
	}
	modint operator - (modint v) const {
		return modint(raw) -= v;
	}
	modint operator * (modint v) const {
		return modint(raw) *= v;
	}
	modint& operator += (modint v) {
		raw += v.raw;
		if (raw >= MOD) { raw -= MOD; }
		return *this;
	}
	modint& operator -= (modint v) {
		raw -= v.raw;
		if (raw < 0) { raw += MOD; }
		return *this;
	}
	modint& operator *= (modint v) {
		raw = (raw * v.raw) % MOD;
		return *this;
	}
};

//------------------------------------------------------------
#if !defined(TEST)
void myMain();
signed main() {
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout << fixed << setprecision(16);
	myMain();
	return 0;
}
#endif

#endif

//------------------------------------------------------------

using mint = modint<998244353>;

int N;
int S;
ints A;
mint dp[3001][3001];

void myMain() {
	N = input;
	S = input;
	A = input(N);

	REP(i, N + 1) {
		REP(j, S + 1) {
			dp[i][j] = 0;
		}
	}

	dp[0][0] = 1;
	REP(i, N) {
		REP(s, S + 1) {
			int ns = s + A[i];
			if (ns <= S) {
				dp[i + 1][ns] += dp[i][s];
			}
			dp[i + 1][s] += dp[i][s] * 2;
		}
	}

	output(dp[N][S].raw);
}


Measured memory_bytes: 74032