unittest
{
	assert( [ "4 1 2 5" ].parse.expand.solve == 40 );
	assert( [ "2 5 6 0" ].parse.expand.solve == 1 );
	assert( [ "90081 33447 90629 6391049189" ].parse.expand.solve == 577742975 );
}



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 nabk = input.front.split.to!( long[] );
	
	return tuple( nabk[ 0 ], nabk[ 1 ], nabk[ 2 ], nabk[ 3 ] );
}

auto solve( long n, long a, long b, long k )
{
	// 緑は赤＋青と同じ
	// つまり、緑は気にせずに赤と青の組み合わせだけ考えればよい
	auto ans = 0L;
	foreach( na; 0L .. n+1 )
	{
		// na個を赤色に塗ったときの点数を計算
		auto ka = na * a;
		
		// 不足している点数を青色で補完する場合の必要な点数と個数を計算
		auto kb = k - ka;
		auto nb = kb / b;
		if( kb % b != 0 || n < nb ) continue;
		
		// 赤パターンと青パターンの組み合わせ数を計算
		auto ca = combinationMod( n, na );
		auto cb = combinationMod( n, nb );
		auto c = ca * cb;
		ans = addMod( ans, c );
	}
	return ans;
}

const MOD = 998244353;

// 足し算
auto addMod( long n, long a )
{
	return ( n + a ) % MOD;
}

// 割り算
auto divMod( long n, long d )
{
	return n * d.powMod( MOD - 2 ) % MOD;
}

// べき乗
long powMod( long n, long p )
{
	static long[ long ][ long ] memo;
	
	if( n !in memo ) memo[ n ][ 0 ] = 1;
	if( p !in memo[ n ] )
	{
		if( p % 2 == 0 ) memo[ n ][ p ] = n.powMod( p / 2 ) ^^ 2 % MOD;
		else             memo[ n ][ p ] = n.powMod( p - 1 ) *  n % MOD;
	}
	
	return memo[ n ][ p ];
}

// 階乗
auto factorialMod( long n )
{
	static memo = appender( [ 1L, 1L ] );
	
	for( auto i = memo.data.length; i <= n; i++ )
	{
		memo.put( memo.data[ $ - 1 ] * i % MOD );
	}
	
	return memo.data[ n ];
}

// 組み合わせ数
auto combinationMod( long n, long r )
{
	return n.factorialMod.divMod( r.factorialMod * ( n - r ).factorialMod % MOD );
}
