macro_rules! eprintln { ($($args:tt)*)
    => { use std::io::Write; writeln!(&mut std::io::stderr(), $($args)*).unwrap(); } }

fn read_line() -> Vec<String> {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).expect("Failed to read line");
    line.trim().split_whitespace().map(|s| s.to_string()).collect()
}
struct Reader { v: Vec<String>, n: usize }
impl Reader {
    fn new() -> Self { Reader { v: read_line(), n: 0 } }
    #[allow(dead_code)]
    fn next<T>(&mut self) -> T where T: std::str::FromStr, T::Err: std::fmt::Debug {
        if self.n == self.v.len() { self.v = read_line(); self.n = 0; }
        self.n += 1; self.v[self.n-1].parse().expect(&self.v[self.n-1]) }
    #[allow(dead_code)]
    fn nexts<T>(&mut self, n: usize) -> Vec<T>
    where T: std::str::FromStr, T::Err: std::fmt::Debug {
        let mut v = Vec::with_capacity(n); for _ in 0..n { v.push(self.next()); } v } }

use std::marker::PhantomData;
use std::ops::{Add, Sub, Mul, AddAssign, SubAssign, MulAssign};
// TODO: associated constants when compiler version is updated
pub trait Modulus { fn n() -> u64; }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MPrime;
impl Modulus for MPrime { fn n() -> u64 { 998244353 } }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Mod<M>(pub u64, PhantomData<M>);

impl<M: Modulus + Copy > Mod<M> {
    pub fn new(x: u64) -> Self { Mod(x % M::n(), PhantomData) }
    pub fn pow(self, n: u64) -> Self {
        match n {
            0 => Mod::new(1),
            n if n % 2 > 0 => self.pow(n-1) * self,
            n => { let x = self.pow(n/2); x * x },
        }
    }
    pub fn inv(self) -> Self { self.pow(M::n()-2) }
}
impl<M: Modulus + Copy> Default for Mod<M> { fn default() -> Self { Mod::new(0) } }
impl<M: Modulus + Copy> From<u64> for Mod<M> { fn from(x: u64) -> Mod<M> { Mod::new(x) } }
impl<M: Modulus + Copy, T: Into<Mod<M>>> Add<T> for Mod<M> { type Output = Mod<M>;
    fn add(self, other: T) -> Mod<M> { Mod::new(self.0 + other.into().0) } }
impl<M: Modulus + Copy, T: Into<Mod<M>>> Sub<T> for Mod<M> { type Output = Mod<M>;
    fn sub(self, other: T) -> Mod<M> { Mod::new((self.0 + M::n() - other.into().0)) } }
impl<M: Modulus + Copy, T: Into<Mod<M>>> Mul<T> for Mod<M> { type Output = Mod<M>;
    fn mul(self, other: T) -> Mod<M> { Mod::new((self.0 * other.into().0)) } }
impl<M: Modulus + Copy> Add<Mod<M>> for u64 { type Output = Mod<M>;
    fn add(self, other: Mod<M>) -> Mod<M> { other.add(self) } }
impl<M: Modulus + Copy> Sub<Mod<M>> for u64 { type Output = Mod<M>;
    fn sub(self, other: Mod<M>) -> Mod<M> { other.sub(self) } }
impl<M: Modulus + Copy> Mul<Mod<M>> for u64 { type Output = Mod<M>;
    fn mul(self, other: Mod<M>) -> Mod<M> { other.mul(self) } }
impl<M: Modulus + Copy, T: Into<Mod<M>>> AddAssign<T> for Mod<M> {
    fn add_assign(&mut self, other: T) { *self = self.add(other); } }
impl<M: Modulus + Copy, T: Into<Mod<M>>> SubAssign<T> for Mod<M> {
    fn sub_assign(&mut self, other: T) { *self = self.sub(other); } }
impl<M: Modulus + Copy, T: Into<Mod<M>>> MulAssign<T> for Mod<M> {
    fn mul_assign(&mut self, other: T) { *self = self.mul(other); } }
pub type M = Mod<MPrime>;

pub struct Combination<M>(Vec<Mod<M>>);
impl<M: Modulus + Copy> Combination<M> {
    pub fn new(n: u64) -> Self {
        let fact: Vec<Mod<M>> = (0..n).scan(1.into(), |s, x| {
            *s = if x == 0 { 1.into() } else { *s * x }; Some(*s)
        }).collect(); Combination(fact)
    }
    pub fn fact(&self, n: u64) -> (Mod<M>, u64) {
        let p = M::n();
        if n < p { return ((self.0)[n as usize], 0); }
        let k = n / p; let (a, e) = self.fact(k.into());
        ((self.0)[(n % p) as usize] * a * ((p - 2) * k % 2 + 1), e + k)
    }
    pub fn comb(&self, n: u64, m: u64) -> Mod<M> {
        if n < m { panic!("{} < {}", n, m); }
        let (an, en) = self.fact(n); let (am, em) = self.fact(m); let (al, el) = self.fact(n-m);
        if en > em + el { 0.into() } else { an * (am * al).inv() }
    }
}

fn main() {
    let mut r = Reader::new();
    let k: i64 = r.next();
    let n: i64 = r.next();
    let c = Combination::new(100000);
    for t in 2..(2 * k + 1) {
        let mut ans: M = 0.into();
        let (mut p, mut s) = (0u64, 0u64);
        for j in 1..(k+1) {
            if 2*j == t { continue; }
            if  1 <= t-j && t-j <= k {
                p += 1;
            } else {
                s += 1;
            }
        }
        p /= 2;

        let mut p2 = M::new(1);
        for q in 0..(p+1) {
            let n = n as u64;
            if q > n { break; }
            if q == 0 && s == 0 {
                p2 *= 2;
                continue;
            }
            let x = c.comb(p, q);
            let y = c.comb(n+s-1, q+s-1);
            //eprintln!("{} {} {} {} {} {} {}", t, p, q, s, x.0, y.0, p2.0);
            ans += x * y * p2;
            if t % 2 == 0 && q < n {
                let y = c.comb(n+s-2, q+s-1);
                ans += x * y * p2;
            }
            p2 *= 2;
        }
        println!("{}", ans.0);
    }

}


Measured memory_bytes: 4476