Problem:
Score : 700 points

Problem Statement

Takahashi throws N dice, each having K sides with all integers from 1 to K. The dice are NOT pairwise distinguishable.
For each i=2,3,...,2K, find the following value modulo 998244353:

The number of combinations of N sides shown by the dice such that the sum of no two different sides is i.

Note that the dice are NOT distinguishable, that is, two combinations are considered different when there exists an integer k such that the number of dice showing k is different in those two.

Constraints

1 \leq K \leq 2000

2 \leq N \leq 2000

K and N are integers.

Input

Input is given from Standard Input in the following format:

K N

Output

Print 2K-1 integers. The t-th of them (1\leq t\leq 2K-1) should be the answer for i=t+1.

Sample Input 1

3 3

Sample Output 1

7
7
4
7
7

For i=2, the combinations (1,2,2),(1,2,3),(1,3,3),(2,2,2),(2,2,3),(2,3,3),(3,3,3) satisfy the condition, so the answer is 7.

For i=3, the combinations (1,1,1),(1,1,3),(1,3,3),(2,2,2),(2,2,3),(2,3,3),(3,3,3) satisfy the condition, so the answer is 7.

For i=4, the combinations (1,1,1),(1,1,2),(2,3,3),(3,3,3) satisfy the condition, so the answer is 4.

Sample Input 2

4 5

Sample Output 2

36
36
20
20
20
36
36

Sample Input 3

6 1000

Sample Output 3

149393349
149393349
668669001
668669001
4000002
4000002
4000002
668669001
668669001
149393349
149393349

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
#define REP(i,n) for (long long i=0;i<(n);i++)
#define FOR(i,a,b) for (long long i=(a);i<(b);i++)
#define RREP(i,n) for(long long i=n;i>=0;i--)
#define RFOR(i,a,b) for(long long i=(a);i>(b);i--)
#define dump1d_arr(array) REP(i,array.size()) cerr << #array << "[" << (i) << "] ==> " << (array[i]) << endl
#define dump2d_arr(array) REP(i,array.size()) REP(j,array[i].size()) cerr << #array << "[" << (i) << "]" << "[" << (j) << "] ==> " << (array[i][j]) << endl
#define dump(x)  cerr << #x << " => " << (x) << endl
#define dumpP(p) cerr << "( " << p.first << " , " << p.second << " )" << ends
#define SORT(c) sort((c).begin(),(c).end())
#define MIN(vec) *min_element(vec.begin(), vec.end())
#define MAX(vec) *max_element(vec.begin(), vec.end())
#define UNIQ(vec) vec.erase(unique(vec.begin(), vec.end()),vec.end()) //ソートの必要あり
#define IN(n,m)  (!(m.find(n) == m.end()))
#define ENUM(m) for (auto itr = m.begin(); itr != m.end(); ++itr)
#define dump_MAP(m) for(auto itr = m.begin(); itr != m.end(); ++itr) { cerr << itr->first << " --> "  << itr->second << endl; }
#define FINDL(vec,x) (lower_bound(vec.begin(),vec.end(),x) - vec.begin())
#define FINDU(vec,x) (upper_bound(vec.begin(),vec.end(),x) - vec.begin())
#define ROUND(N) setprecision(N)
#define ROUND_PRINT(N,val) cout << fixed;cout << setprecision(N) << val << endl
#define ALL(a)  (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define INARR(h,w,x,y) (0 <= y && y < h && 0 <= x && x < w)
#define EQ(a,b) (abs(a - b) < 1e-10)
using namespace std;
constexpr int dx[4] = {0,1,0,-1};
constexpr int dy[4] = {1,0,-1,0};
constexpr long double pi = M_PI;
constexpr double eps = 1e-10;
constexpr long mod = 1000000007;
constexpr short shINF = 32767;
constexpr long loINF = 2147483647;
constexpr long long llINF = 9223372036854775807;
typedef long long LL;
typedef vector<LL> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<LL,LL> pr;
typedef vector<bool> VB;
typedef vector<pr> VP;
typedef priority_queue<pr,vector<pr>,greater<pr>> pq;

template <typename T>
class modCal {
private:
    T mod;
public:
    modCal(T m = 1000000007) : mod(m) {}
    T add(T a,T b) {
        a += b;
        if (a >= mod) a -= mod;
        return a;
    }
 
    T sub(T a,T b) {
        a -= b;
        if (a < 0) a += mod;
        return a;
    }
 
    T mul(T a,T b) {
        return (T)((long long)a * b % mod);
    }
 
    T power(T a, long long b) {
        T res = 1;
        while (b > 0) {
            if (b & 1) {
                res = mul(res, a);
            }
            a = mul(a, a);
            b >>= 1;
        }
        return res;
    }
 
    T inv(T a) {
        a %= mod;
        if (a < 0) a += mod;
        T b = mod, u = 0, v = 1;
        while (a) {
            T t = b / a;
            b -= t * a; swap(a, b);
            u -= t * v; swap(u, v);
        }
        assert(b == 1);
        if (u < 0) u += mod;
        return u;
    }
 
    T div(T &a,T b) {
        return mul(a,inv(b));
    }
 
    T nCr_mod(T n,T r) {
        if (n < 0 || r < 0 || n < r) return 0;
        r = min(r,n-r);
        T v = 1;
        for (T i = 0;i < r;i++) {
            v = mul(v,mul(n-i,inv(r-i)));
        }
        return v;
    }
 
    vector<T> nCr_alln(T n) {
        if (n < 0) return vector<T>(0);
        vector<T> ret(n+1,1);
        for (T i = 1;i <= n;i++) {
            ret[i] = mul(ret[i-1],mul(n-i+1,inv(i)));
        }
        return ret;
    }
 
    vector<T> fact_mod(T n) {
        vector<T> fact(n+1,1);
        for (T i = 2;i <= n;i ++) fact[i] = mul(fact[i-1],i);
        return fact;
    }
 
    vector<T> fact_inv_mod(T n) {
        vector<T> fact_inv(n+1,1);
        for (T i = 1;i <= n;i++) fact_inv[i] = mul(fact_inv[i-1],inv(i));
        return fact_inv;
    }
};

int main(void) {
    cin.tie(0);
    ios::sync_with_stdio(false);
    modCal<LL> md(998244353);
    LL N,K,p;
    cin >> K >> N;
    FOR(i,2,2*K+1) {
        // pair数
        if (i > (K+1)) p = (2*(K+1) - i) / 2;
        else p = i/2;
        // メモ化
        LL tmp = N+K-2*p-1;
        vector<LL> nCr = md.nCr_alln(tmp);
        vector<LL> pCq = md.nCr_alln(p-1);
        LL ans = 0;
        LL itermx = min(p+1,N+1);
        LL item1 , item2 , item3 , item4 , pow2q_ = 1 , prev = 0;
        if (i % 2) { // 奇数の場合
            REP(q,itermx) {
                item1 = (q >= 0 && (p-1) >= q) ? pCq[q] : 0;
                item2 = ((q-1) >= 0 && (p-1) >= (q-1)) ? pCq[q-1] : 0;
                item3 = (N-q >= 0 && tmp >= (N-q)) ? nCr[N-q] : 0;
                ans = 
                    md.add( ans, 
                            md.mul( item3 ,
                                md.mul(
                                    md.add(item1,item2),
                                    pow2q_
                                )
                            )
                        );
                pow2q_ = md.mul(pow2q_ , 2);
            }
        }
        else { // 偶数の場合
            REP(q,itermx) {
                item1 = (q >= 0 && (p-1) >= q) ? pCq[q] : 0;
                item2 = ((q-1) >= 0 && (p-1) >= (q-1)) ? pCq[q-1] : 0;
                item3 = (N-q >= 0 && tmp >= (N-q)) ? nCr[N-q] : 0;
                item4 = ((N-q-1) >= 0 && tmp >= (N-q-1)) ? nCr[N-q-1] : 0;
                ans = md.add ( ans , 
                            md.add (
                                md.mul (
                                    item1 ,
                                    md.mul ( pow2q_ , md.add(item3,item4) )    
                                ),
                                md.mul (
                                    item2,
                                    md.mul ( prev , item3 )

                                )
                            )
                        );
                prev = pow2q_;
                pow2q_ = md.mul( pow2q_ , 2);
            }
        }
        cout <<  ans << endl;
    }
}