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# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static System.Console;
using static System.Math;

namespace AtTest._700problems
{
    class ARC102_E
    {
        static void Main(string[] args)
        {
            var sw = new System.IO.StreamWriter(OpenStandardOutput()) { AutoFlush = false };
            SetOut(sw);

            Method(args);

            Out.Flush();
        }

        static void Method(string[] args)
        {
            long[] kn = ReadLongs();
            long k = kn[0];
            long n = kn[1];
            long mask = 998244353;

            long[] perms = AllPermutations(k + n - 1, mask);

            long allPat = Multi(perms[k + n - 1],
                Reverse(Multi(perms[k - 1], perms[n], mask), mask - 2, mask), mask);

            long[] res = new long[2 * k - 1];
            for(long val = 2; val <= k+1; val++)
            {
                long pats = Min(val - 2, 2 * k - val) / 2 + 1;
                long seqCnt = Min(pats, n / 2);
                long resTmp = allPat;
                for (long i = 1; i <= seqCnt; i++)
                {
                    long tmp = Multi(perms[pats],
                        Reverse(Multi(perms[i], perms[pats - i], mask),
                        mask - 2, mask), mask);
                    tmp = Multi(tmp,
                        Multi(perms[k - 1 + n - i * 2],
                        Reverse(Multi(perms[k - 1], perms[n - i * 2], mask),
                            mask - 2, mask), mask), mask);
                    if (i % 2 == 1)
                    {
                        resTmp += mask - tmp;
                    }
                    else
                    {
                        resTmp += tmp;
                    }
                    resTmp %= mask;
                }

                res[val - 2] = resTmp;
                res[2 * k - val] = resTmp;
            }

            for (int i = 0; i < 2 * k - 1; i++) WriteLine(res[i]);
        }

        static long[] AllPermutations(long n, long mask)
        {
            var perms = new long[n + 1];
            perms[0] = 1;
            for (int i = 1; i <= n; i++)
            {
                perms[i] = Multi(perms[i - 1], i, mask);
            }
            return perms;
        }

        static long Multi(long a, long b, long mask)
        {
            return ((a % mask) * (b % mask)) % mask;
        }

        static long Reverse(long a, long pow, long mask)
        {
            if (pow == 0) return 1;
            else if (pow == 1) return a % mask;
            else
            {
                long halfMod = Reverse(a, pow / 2, mask);
                long nextMod = Multi(halfMod, halfMod, mask);
                if (pow % 2 == 0)
                {
                    return nextMod;
                }
                else
                {
                    return Multi(nextMod, a, mask);
                }
            }
        }

        /*
        static ModLong Combination(ModLong n,ModLong m)
        {
            if (n.value < m.value) return new ModLong(0);

            if (n - m < m) m = n - m;

            long val = Permutation(n, m, mask);
            long div = Permutation(m, m, mask);
            return MultiMod(val, ReverseMod(div, mask - 2, mask), mask);
        }

        static long Permutation(ModLong n, ModLong m)
        {
            ModLong val = new ModLong(1);
            for (long i = 0; i < m; i++)
            {
                val *= ((n - i) % mask);
                val %= mask;
            }
            return val;
        }

        static long[] AllPermutations(long n, long mask)
        {
            var perms = new long[n + 1];
            perms[0] = 1;
            for (int i = 1; i <= n; i++)
            {
                perms[i] = MultiMod(perms[i - 1], i, mask);
            }
            return perms;
        }

        static long MultiMod(long a, long b, long mask)
        {
            return ((a % mask) * (b % mask)) % mask;
        }

        static long ReverseMod(long a, long pow, long mask)
        {
            if (pow == 0) return 1;
            else if (pow == 1) return a % mask;
            else
            {
                long halfMod = ReverseMod(a, pow / 2, mask);
                long nextMod = MultiMod(halfMod, halfMod, mask);
                if (pow % 2 == 0)
                {
                    return nextMod;
                }
                else
                {
                    return MultiMod(nextMod, a, mask);
                }
            }
        }

        struct ModLong
        {
            public static long mask = 1000000000 + 7;//default

            public long value;

            public ModLong(long value)
            {
                this.value = value;
            }

            public static ModLong operator +(ModLong a, ModLong b)
            {
                long val = (a.value + b.value) % mask;
                return new ModLong(val);
            }

            public static ModLong operator +(ModLong a, long b)
            {
                long val = (a.value + b) % mask;
                return new ModLong(val);
            }

            public static ModLong operator +(long a, ModLong b)
            {
                long val = (a + b.value) % mask;
                return new ModLong(val);
            }

            public static ModLong operator -(ModLong a, ModLong b)
            {
                long val = a.value - b.value;
                while (val < 0) val += mask;
                return new ModLong(val);
            }

            public static ModLong operator -(ModLong a, long b)
            {
                long val = a.value - b;
                while (val < 0) val += mask;
                return new ModLong(val);
            }

            public static ModLong operator -(long a, ModLong b)
            {
                long val = a - b.value;
                while (val < 0) val += mask;
                return new ModLong(val);
            }

            public static ModLong operator *(ModLong a, ModLong b)
            {
                long val=(a.value*b.value)% mask;
                return new ModLong(val);
            }

            public static ModLong operator *(ModLong a, long b)
            {
                long val = (a.value * b) % mask;
                return new ModLong(val);
            }

            public static ModLong operator *(long a, ModLong b)
            {
                long val = (a * b.value) % mask;
                return new ModLong(val);
            }

            public static ModLong operator /(ModLong a, ModLong b)
            {
                long val = (a.value * Reverse(b.value, mask - 2)) % mask;
                return new ModLong(val);
            }

            public static ModLong operator /(ModLong a, long b)
            {
                long val = (a.value * Reverse(b, mask - 2)) % mask;
                return new ModLong(val);
            }

            public static ModLong operator /(long a, ModLong b)
            {
                long val = (a * Reverse(b.value, mask - 2)) % mask;
                return new ModLong(val);
            }

            static long Reverse(long val,long pow)
            {
                if (pow == 0) return 1;
                else if (pow == 1) return val % mask;
                else
                {
                    long halfMod = Reverse(val, pow / 2);
                    long nextMod = (halfMod * halfMod) % mask;
                    if (pow % 2 == 0)
                    {
                        return nextMod;
                    }
                    else
                    {
                        return (nextMod * val) % mask;
                    }
                }
            }
        }
        */

        private static string Read() { return ReadLine(); }
        private static char[] ReadChars() { return Array.ConvertAll(Read().Split(), a => a[0]); }
        private static int ReadInt() { return int.Parse(Read()); }
        private static long ReadLong() { return long.Parse(Read()); }
        private static double ReadDouble() { return double.Parse(Read()); }
        private static int[] ReadInts() { return Array.ConvertAll(Read().Split(), int.Parse); }
        private static long[] ReadLongs() { return Array.ConvertAll(Read().Split(), long.Parse); }
        private static double[] ReadDoubles() { return Array.ConvertAll(Read().Split(), double.Parse); }
    }
}