unittest
{
	assert( [ "3 4", "2 2 4" ].parse.expand.solve == 6 );
	assert( [ "5 8", "9 9 9 9 9" ].parse.expand.solve == 0 );
	assert( [ "10 10", "3 1 4 1 5 9 2 6 5 3" ].parse.expand.solve == 3296 );
}



import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto ns = input.front.split.to!( long[] );
	input.popFront;
	auto as = input.front.split.to!( long[] );
	return tuple( ns[ 1 ], as );
}

auto solve( long s, long[] as )
{
	const M = 998244353;
	
	// dp[ i番目 ][ 入れたaの合計 ][ 入れたaの個数 ] = パターン数
	auto dp = new ModWorld!M[ long ][][]( 1 + as.length, 1 + s );
	dp[ 0 ][ 0 ][ 0 ] = ModWorld!M( 1 );
	foreach( i, a; as )
	{
		foreach( j; 0L .. dp[ i ].length.signed )
		{
			foreach( k; dp[ i ][ j ].keys )
			{
				// 入れない
				if( k !in dp[ i + 1 ][ j ] ) dp[ i + 1 ][ j ][ k ]  = dp[ i ][ j ][ k ];
				else                         dp[ i + 1 ][ j ][ k ] += dp[ i ][ j ][ k ];
				
				// 入れる
				if( j + a < dp[ i ].length )
				{
					if( k + 1 !in dp[ i + 1 ][ j + a ] ) dp[ i + 1 ][ j + a ][ k + 1 ]  = dp[ i ][ j ][ k ];
					else                                 dp[ i + 1 ][ j + a ][ k + 1 ] += dp[ i ][ j ][ k ];
				}
			}
		}
	}
	
	// サブセットの数だけ掛け算する
	auto ans = ModWorld!M( 0 );
	foreach( k; dp[ $ - 1 ][ $ - 1 ].keys )
	{
		ans += dp[ $ - 1 ][ $ - 1 ][ k ] * ( ModWorld!M( 2 ) ^^ ( as.length.signed - k ) );
	}
	return ans;
}

// モジュラ整数型（n mod M）
struct ModWorld( long M )
{
	long n;
	
	void opUnary( string OP )() if( OP == "++" ){ this.n = ( this.n + 1 ) % M; }
	void opUnary( string OP )() if( OP == "--" ){ this.n = ( this.n + M - 1 ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "+"  ){ this.n = ( this.n + r.n ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "-"  ){ this.n = ( this.n + M - r.n ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "*"  ){ this.n = ( this.n * r.n ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "/"  ){ this *= r ^^ ModWorld( M - 2 ); }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "^^" )
	{
		auto a = this.n;
		this.n = 1L;
		for( auto i = r.n; 0 < i; i >>= 1 )
		{
			if( i & 1 ) this.n = ( this.n * a ) % M;
			a = ( a * a ) % M;
		}
	}
	auto opBinary( string OP )( ModWorld r ){ auto l = this; l.opOpAssign!OP( r ); return l; }
	
	void opAssign( long r ){ this.n = r; }
	void opOpAssign( string OP )( long r ){ this.opOpAssign!OP( ModWorld( r ) ); }
	auto opBinary( string OP )( long r ){ return this.opBinary!OP( ModWorld( r ) ); }
	auto opBinaryRight( string OP )( long l ){ return ModWorld( l ).opBinary!OP( this ); }
	auto opEquals( long r ){ return this.n == r; }
	
	auto toString(){ return this.n.to!string; }
}
