//header
#ifdef LOCAL
    #include "cxx-prettyprint-master/prettyprint.hpp"
    #define debug(x) cout << x << endl
#else
    #define debug(...) 42
#endif
    #pragma GCC optimize("Ofast")
    #include <bits/stdc++.h>
    //types
    using namespace std;
    using ll = long long;
    using ul = unsigned long long;
    using ld = long double;
    typedef pair < ll , ll > Pl;        
    typedef pair < int, int > Pi;
    typedef vector<ll> vl;
    typedef vector<int> vi;
    template< typename T >
    using mat = vector< vector< T > >;
    template< int mod >
    struct modint {
        int x;

        modint() : x(0) {}

        modint(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

        modint &operator+=(const modint &p) {
            if((x += p.x) >= mod) x -= mod;
            return *this;
        }

        modint &operator-=(const modint &p) {
            if((x += mod - p.x) >= mod) x -= mod;
            return *this;
        }

        modint &operator*=(const modint &p) {
            x = (int) (1LL * x * p.x % mod);
            return *this;
        }

        modint &operator/=(const modint &p) {
            *this *= p.inverse();
            return *this;
        }

        modint operator-() const { return modint(-x); }

        modint operator+(const modint &p) const { return modint(*this) += p; }

        modint operator-(const modint &p) const { return modint(*this) -= p; }

        modint operator*(const modint &p) const { return modint(*this) *= p; }

        modint operator/(const modint &p) const { return modint(*this) /= p; }

        bool operator==(const modint &p) const { return x == p.x; }

        bool operator!=(const modint &p) const { return x != p.x; }

        modint inverse() const {
            int a = x, b = mod, u = 1, v = 0, t;
            while(b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
            }
            return modint(u);
        }

        modint pow(int64_t n) const {
            modint ret(1), mul(x);
            while(n > 0) {
            if(n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
            }
            return ret;
        }

        friend ostream &operator<<(ostream &os, const modint &p) {
            return os << p.x;
        }

        friend istream &operator>>(istream &is, modint &a) {
            int64_t t;
            is >> t;
            a = modint< mod >(t);
            return (is);
        }

        static int get_mod() { return mod; }
    };
    //abreviations
    #define all(x) (x).begin(), (x).end()
    #define rall(x) (x).rbegin(), (x).rend()
    #define rep_(i, a_, b_, a, b, ...) for (int i = (a), max_i = (b); i < max_i; i++)
    #define rep(i, ...) rep_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
    #define rrep_(i, a_, b_, a, b, ...) for (int i = (b-1), min_i = (a); i >= min_i; i--)
    #define rrep(i, ...) rrep_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
    #define SZ(x) ((int)(x).size())
    #define pb(x) push_back(x)
    #define eb(x) emplace_back(x)
    #define mp make_pair
    #define print(x) cout << x << endl
    #define vsum(x) accumulate(x, 0LL)
    #define vmax(a) *max_element(all(a))
    #define vmin(a) *min_element(all(a))
    //functions
    ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
    ll lcm(ll a, ll b) { return a/gcd(a, b)*b;}
    template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
    template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
    template< typename T >
    T mypow(T x, ll n) {
        T ret = 1;
        while(n > 0) {
            if(n & 1) (ret *= x);
            (x *= x);
            n >>= 1;
        }
        return ret;
    }
    ll modpow(ll x, ll n, const ll mod) {
        ll ret = 1;
        while(n > 0) {
            if(n & 1) (ret *= x);
            (x *= x);
            n >>= 1;
            x%=mod;
            ret%=mod;
        }
        return ret;
    }
    uint64_t my_rand(void) {
        static uint64_t x = 88172645463325252ULL;
        x = x ^ (x << 13); x = x ^ (x >> 7);
        return x = x ^ (x << 17);
    }
    //graph template
    template< typename T >
    struct edge {
        int src, to;
        T cost;

        edge(int to, T cost) : src(-1), to(to), cost(cost) {}

        edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

        edge &operator=(const int &x) {
            to = x;
            return *this;
        }
        operator int() const { return to; }
    };
    template< typename T >
    using Edges = vector< edge< T > >;
    template< typename T >
    using WeightedGraph = vector< Edges< T > >;
    using UnWeightedGraph = vector< vector< int > >;

//constant
#define INF 4001002003004005006LL
#define inf 1000000005
#define mod 998244353LL
#define endl '\n'
typedef modint<mod> mint;
const long double eps = 0.001;
const long double PI  = 3.141592653589793;
//library
struct NumberTheoreticTransform {

    vector< int > rev, rts;
    int base, max_base, root;

    NumberTheoreticTransform() : base(1), rev{0, 1}, rts{0, 1} {
        assert(mod >= 3 && mod % 2 == 1);
        auto tmp = mod - 1;
        max_base = 0;
        while(tmp % 2 == 0) tmp >>= 1, max_base++;
        root = 2;
        while(mod_pow(root, (mod - 1) >> 1) == 1) ++root;
        assert(mod_pow(root, mod - 1) == 1);
        root = mod_pow(root, (mod - 1) >> max_base);
    }

    inline int mod_pow(int x, int n) {
        int ret = 1;
        while(n > 0) {
            if(n & 1) ret = mul(ret, x);
            x = mul(x, x);
            n >>= 1;
        }
        return ret;
    }

    inline int inverse(int x) {
        return mod_pow(x, mod - 2);
    }

    inline unsigned add(unsigned x, unsigned y) {
        x += y;
        if(x >= mod) x -= mod;
        return x;
    }

    inline unsigned mul(unsigned a, unsigned b) {
        return 1ull * a * b % (unsigned long long) mod;
    }

    void ensure_base(int nbase) {
        if(nbase <= base) return;
        rev.resize(1 << nbase);
        rts.resize(1 << nbase);
        for(int i = 0; i < (1 << nbase); i++) {
            rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
        }
        assert(nbase <= max_base);
        while(base < nbase) {
            int z = mod_pow(root, 1 << (max_base - 1 - base));
            for(int i = 1 << (base - 1); i < (1 << base); i++) {
                rts[i << 1] = rts[i];
                rts[(i << 1) + 1] = mul(rts[i], z);
            }
            ++base;
        }
    }


    void ntt(vector< int > &a) {
        const int n = (int) a.size();
        assert((n & (n - 1)) == 0);
        int zeros = __builtin_ctz(n);
        ensure_base(zeros);
        int shift = base - zeros;
        for(int i = 0; i < n; i++) {
            if(i < (rev[i] >> shift)) {
                swap(a[i], a[rev[i] >> shift]);
            }
        }
        for(int k = 1; k < n; k <<= 1) {
            for(int i = 0; i < n; i += 2 * k) {
                for(int j = 0; j < k; j++) {
                    int z = mul(a[i + j + k], rts[j + k]);
                    a[i + j + k] = add(a[i + j], mod - z);
                    a[i + j] = add(a[i + j], z);
                }
            }
        }
    }


    vector< int > multiply(const vector< mint > &a, const vector< mint > &b) {
        int need = a.size() + b.size() - 1;
        int nbase = 1;
        while((1 << nbase) < need) nbase++;
        ensure_base(nbase);
        int sz = 1 << nbase;
        vector< int > fa(sz);
        for(int i = 0; i < a.size(); i++) {
                fa[i] = a[i].x;
        }
        ntt(fa);
        vector< int > fb(sz);
        for(int i = 0; i < b.size(); i++) {
                fb[i] = b[i].x;
        }
        ntt(fb);
        int inv_sz = inverse(sz);
        for(int i = 0; i < sz; i++) {
            fa[i] = mul(fa[i], mul(fb[i], inv_sz));
        }
        reverse(fa.begin() + 1, fa.end());
        ntt(fa);
        fa.resize(need);
        return fa;
    }
};
template< typename T >
struct FormalPowerSeries : vector< T > {
    using vector< T >::vector;
    using P = FormalPowerSeries;

    using MULT = function< P(P, P) >;

    static MULT &get_mult() {
        static MULT mult = nullptr;
        return mult;
    }

    static void set_fft(MULT f) {
        get_mult() = f;
    }

    void shrink() {
        while(this->size() && this->back() == T(0)) this->pop_back();
    }

    P operator+(const P &r) const { return P(*this) += r; }

    P operator+(const T &v) const { return P(*this) += v; }

    P operator-(const P &r) const { return P(*this) -= r; }

    P operator-(const T &v) const { return P(*this) -= v; }

    P operator*(const P &r) const { return P(*this) *= r; }

    P operator*(const T &v) const { return P(*this) *= v; }

    P operator/(const P &r) const { return P(*this) /= r; }

    P operator%(const P &r) const { return P(*this) %= r; }

    P &operator+=(const P &r) {
        if(r.size() > this->size()) this->resize(r.size());
        for(int i = 0; i < r.size(); i++) (*this)[i] += r[i];
        return *this;
    }

    P &operator+=(const T &r) {
        if(this->empty()) this->resize(1);
        (*this)[0] += r;
        return *this;
    }

    P &operator-=(const P &r) {
        if(r.size() > this->size()) this->resize(r.size());
        for(int i = 0; i < r.size(); i++) (*this)[i] -= r[i];
        shrink();
        return *this;
    }

    P &operator-=(const T &r) {
        if(this->empty()) this->resize(1);
        (*this)[0] -= r;
        shrink();
        return *this;
    }

    P &operator*=(const T &v) {
        const int n = (int) this->size();
        for(int k = 0; k < n; k++) (*this)[k] *= v;
        return *this;
    }

    P &operator*=(const P &r) {
        if(this->empty() || r.empty()) {
            this->clear();
            return *this;
        }
        assert(get_mult() != nullptr);
        return *this = get_mult()(*this, r);
    }

    P &operator%=(const P &r) {
        return *this -= *this / r * r;
    }

    P operator-() const {
        P ret(this->size());
        for(int i = 0; i < this->size(); i++) ret[i] = -(*this)[i];
        return ret;
    }

    P &operator/=(const P &r) {
        if(this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int n = this->size() - r.size() + 1;
        return *this = (rev().pre(n) * r.rev().inv(n)).pre(n).rev(n);
    }

    P pre(int sz) const {
        return P(begin(*this), begin(*this) + min((int) this->size(), sz));
    }

    P operator>>(int sz) const {
        if(this->size() <= sz) return {};
        P ret(*this);
        ret.erase(ret.begin(), ret.begin() + sz);
        return ret;
    }

    P operator<<(int sz) const {
        P ret(*this);
        ret.insert(ret.begin(), sz, T(0));
        return ret;
    }

    P rev(int deg = -1) const {
        P ret(*this);
        if(deg != -1) ret.resize(deg, T(0));
        reverse(begin(ret), end(ret));
        return ret;
    }

    P diff() const {
        const int n = (int) this->size();
        P ret(max(0, n - 1));
        for(int i = 1; i < n; i++) ret[i - 1] = (*this)[i] * T(i);
        return ret;
    }

    P integral() const {
        const int n = (int) this->size();
        P ret(n + 1);
        ret[0] = T(0);
        for(int i = 0; i < n; i++) ret[i + 1] = (*this)[i] / T(i + 1);
        return ret;
    }

    // F(0) must not be 0
    P inv(int deg = -1) const {
        assert(((*this)[0]) != T(0));
        const int n = (int) this->size();
        if(deg == -1) deg = n;
        P ret({T(1) / (*this)[0]});
        for(int i = 1; i < deg; i <<= 1) {
            ret = (ret + ret - ret * ret * pre(i << 1)).pre(i << 1);
        }
        return ret.pre(deg);
    }

    // F(0) must be 1
    P log(int deg = -1) const {
        assert((*this)[0] == 1);
        const int n = (int) this->size();
        if(deg == -1) deg = n;
        return (this->diff() * this->inv(deg)).pre(deg - 1).integral();
    }

    P sqrt(int deg = -1) const {
        const int n = (int) this->size();
        if(deg == -1) deg = n;

        if((*this)[0] == T(0)) {
            for(int i = 1; i < n; i++) {
                if((*this)[i] != T(0)) {
                    if(i & 1) return {};
                    if(deg - i / 2 <= 0) break;
                    auto ret = (*this >> i).sqrt(deg - i / 2) << (i / 2);
                    if(ret.size() < deg) ret.resize(deg, T(0));
                    return ret;
                }
            }
            return P(deg, 0);
        }

        P ret({T(1)});
        T inv2 = T(1) / T(2);
        for(int i = 1; i < deg; i <<= 1) {
            ret = (ret + pre(i << 1) * ret.inv(i << 1)) * inv2;
        }
        return ret.pre(deg);
    }

    // F(0) must be 0
    P exp(int deg = -1) const {
        assert((*this)[0] == T(0));
        const int n = (int) this->size();
        if(deg == -1) deg = n;
        P ret({T(1)});
        for(int i = 1; i < deg; i <<= 1) {
            ret = (ret * (pre(i << 1) + T(1) - ret.log(i << 1))).pre(i << 1);
        }
        return ret.pre(deg);
    }

    P pow(int64_t k, int deg = -1) const {
        const int n = (int) this->size();
        if(deg == -1) deg = n;
        for(int i = 0; i < n; i++) {
            if((*this)[i] != T(0)) {
                T rev = T(1) / (*this)[i];
                P C(*this * rev);
                P D(n - i);
                for(int j = i; j < n; j++) D[j - i] = C[j];
                D = (D.log() * k).exp() * (*this)[i].pow(k);
                P E(deg);
                if(i * k > deg) return E;
                auto S = i * k;
                for(int j = 0; j + S < deg && j < D.size(); j++) E[j + S] = D[j];
                return E;
            }
        }
        return *this;
    }


    T eval(T x) const {
        T r = 0, w = 1;
        for(auto &v : *this) {
            r += w * v;
            w *= x;
        }
        return r;
    }
};
/* how to use
// you can use ntt instead.
//with fft
ArbitraryModConvolution<mint> arb;
using FPS = FormalPowerSeries< mint >;
auto mult = [&](const FPS::P &a, const FPS::P &b) {
        auto ret = arb.multiply(a, b);
        return FPS::P(ret.begin(), ret.end());
};
FPS::set_fft(mult);
//with loop
using FPS = FormalPowerSeries< mint >;
auto mult = [&](const FPS::P &a, const FPS::P &b) {
    vi c(a.size()+b.size()-1);
    rep(i, a.size())rep(j, b.size()){
        c[i+j]+=a[i]*b[j];
    }
    return FPS::P(c.begin(), c.end())
};
FPS::set_fft(mult);
//ntt
NumberTheoreticTransform arb;
    using FPS = FormalPowerSeries< mint >;
    auto mult = [&](const FPS::P &a, const FPS::P &b) {
            auto ret = arb.multiply(a, b);
            return FPS::P(ret.begin(), ret.end());
    };
//example
FormalPowerSeries< mint > X(K + 1);
*/
int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    cout << setprecision(20);
    int n; cin>>n;
    int s; cin>>s;
    vi a(n);
    rep(i, n){
        cin>>a[i];
    }
    vector<mint> F(s+1);
    F[0] = mypow<mint>(2, n);
    rep(i, n){
        vector<mint> tmp(s+1);
        tmp = F;
        rep(j, s+1){
            if(j+a[i]>s)break;
            tmp[j+a[i]]+=F[j]/2;
        }
        F = tmp;
    }
    cout << F[s] << endl;
} 

Measured memory_bytes: 3628