#![allow(non_snake_case,unused_imports,dead_code)]
use std::io::Read;
use std::cmp::max;
use std::cmp::min;
use std::str::FromStr;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::BinaryHeap;

fn main() {
    let mut buf = String::new();
    std::io::stdin().read_to_string(&mut buf).unwrap();
    let mut buf_it = buf.split_whitespace();

    let N = buf_it.next().unwrap().parse::<usize>().unwrap();
    let A = buf_it.next().unwrap().parse::<isize>().unwrap();
    let B = buf_it.next().unwrap().parse::<isize>().unwrap();
    let K = buf_it.next().unwrap().parse::<isize>().unwrap();

    let MOD = 998244353;
    let mut ans = ModInt::new(0,MOD);
    let mut fact = ModFact::new(0,MOD);
    for i in 0..N+1{
        let i = i as isize;
        if (K-A*i)%B!=0{ continue;}
        let j = (K-A*i)/B;
        if j<0 || j>N as isize { continue;}
        ans = ans + fact.comb(N,i as usize) * fact.comb(N,j as usize);
    }
    println!("{}",ans.n);
}

use std::ops::{Add, Sub, Mul, Div};

#[derive(Copy, Clone)]
struct ModInt{
    n: isize,
    m: isize
}

impl ModInt {
    fn new(n:isize,m:isize) -> ModInt{
        ModInt {n:(n%m+m)%m, m:m}
    }
    fn pow_mod(a:isize,b:isize,m:isize) -> isize{
        if b==0{ return 1;}
        if b%2==1{ return a*ModInt::pow_mod(a,b-1,m)%m}
        ModInt::pow_mod(a*a%m,b/2,m)
    }
    fn inv(self) -> ModInt{
        let n = ModInt::pow_mod(self.n,self.m-2,self.m);
        ModInt::new(n,self.m)
    }
}
impl Add for ModInt{
    type Output = ModInt;
    fn add(self, other:ModInt) -> ModInt
    {
        ModInt::new(self.n+ other.n,self.m)
    }
}
impl Add<isize> for ModInt{
    type Output = ModInt;
    fn add(self, other:isize) -> ModInt
    {
        ModInt::new(self.n+ other,self.m)
    }
}
impl Sub for ModInt{
    type Output = ModInt;
    fn sub(self, other:ModInt) -> ModInt
    {
        ModInt::new(self.n-other.n,self.m)
    }
}
impl Sub<isize> for ModInt{
    type Output = ModInt;
    fn sub(self, other:isize) -> ModInt
    {
        ModInt::new(self.n-other,self.m)
    }
}
impl Mul for ModInt{
    type Output = ModInt;
    fn mul(self, other:ModInt) -> ModInt
    {
        ModInt::new(self.n*other.n,self.m)
    }
}
impl Mul<isize> for ModInt{
    type Output = ModInt;
    fn mul(self, other:isize) -> ModInt
    {
        ModInt::new(self.n*other,self.m)
    }
}
impl Div for ModInt{
    type Output = ModInt;
    fn div(self, other:ModInt) -> ModInt
    {
        other.inv() * self
    }
}
impl Div<isize> for ModInt{
    type Output = ModInt;
    fn div(self, other:isize) -> ModInt
    {
        ModInt::new(other,self.m).inv() * self
    }
}


struct ModFact{
    n: usize,
    m: isize,
    fac: Vec<ModInt>,
    inv_fac: Vec<ModInt>
}

impl ModFact{
    fn new(n:usize,m:isize) -> ModFact{
        let f = vec![ModInt::new(1,m)];
        let inv_f = vec![ModInt::new(1,m)];
        let mut ret = ModFact{n:0,m:m,fac:f,inv_fac:inv_f};
        ret.update(n);
        ret
    }
    fn get_fact(&mut self,n:usize) -> ModInt{
        if n > self.n {self.update(n);}
        self.fac[n]
    }
    fn get_inv_fact(&mut self,n:usize) -> ModInt{
        if n > self.n {self.update(n);}
        self.inv_fac[n]
    }
    fn update(&mut self,goal:usize){
        let start = self.n+1;
        let mut new_fac = (start..goal+1).map(|_| ModInt::new(1,self.m)).collect::<Vec<_>>();
        self.fac.append(&mut new_fac);
        for i in start..goal+1{
            self.fac[i] = self.fac[i-1] * i as isize ;
        }
        let mut new_inv = (start..goal+1).map(|_| ModInt::new(1,self.m)).collect::<Vec<_>>();
        self.inv_fac.append(&mut new_inv);
        self.inv_fac[goal] = self.fac[goal].inv();
        for j in (start..goal).rev(){
            self.inv_fac[j] = self.inv_fac[j+1]*(j+1) as isize;
        }
        self.n = goal;
    }
    fn comb(&mut self,n:usize,r:usize) -> ModInt{
        self.get_fact(n)*self.get_inv_fact(r)*self.get_inv_fact(n-r)
    }
}


Measured memory_bytes: 28924