// #define LOCAL #define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; template ostream& operator <<(ostream& out, const pair& a) { out << "(" << a.first << "," << a.second << ")"; return out; } template ostream& operator <<(ostream& out, const array& a) { out << "["; bool first = true; for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]"; return out; } template ostream& operator <<(ostream& out, const vector& a) { out << "["; bool first = true; for (auto v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]"; return out; } template ostream& operator <<(ostream& out, const set& a) { out << "{"; bool first = true; for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "}"; return out; } template ostream& operator <<(ostream& out, const map& a) { out << "{"; bool first = true; for (auto& p : a) { out << (first ? "" : ", "); out << p.first << ":" << p.second; first = 0;} out << "}"; return out; } #ifdef LOCAL #define trace(...) __f(#__VA_ARGS__, __VA_ARGS__) #else #define trace(...) 42 #endif template void __f(const char* name, Arg1&& arg1){ cerr << name << ": " << arg1 << endl; } template void __f(const char* names, Arg1&& arg1, Args&&... args){ const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << ": " << arg1 << " |"; __f(comma + 1, args...); } template auto vect(const T& v, int n) { return vector(n, v); } template auto vect(const T& v, int n, D... m) { return vector(n, vect(v, m...)); } typedef long long int64; typedef pair ii; #define SZ(x) (int)((x).size()) template static constexpr T inf = numeric_limits::max() / 2; // const int MOD = 1e9 + 7; const int MOD = 998244353; mt19937 mrand(random_device{}()); int rnd(int x) { return mrand() % x; } // mt19937_64 mrand(random_device{}()); // int64 rnd(int64 x) { return mrand() % x; } template void out(const vector& a) { for (int i = 0; i < SZ(a); ++i) cout << a[i] << " \n"[i + 1 == SZ(a)]; } template bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; } template bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; } template void dedup(vector& v) { sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); } void add(int& x, int y) { x += y; if (x >= MOD) x -= MOD; } struct fast_ios { fast_ios() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(10); }; } fast_ios_; // const int MOD = 998244353; // prime, 2^23*7*17+1 typedef int atom; const int G = 3; int64 power_mod(int64 a, int64 n, int p = MOD) { int64 ret = 1; for (; n; n >>= 1) { if (n & 1) ret = ret * a % p; a = a * a % p; } return ret; } int64 inv_mod(int64 a) { return power_mod(a, MOD - 2); } void bit_reverse(vector& a) { int n = a.size(); for (int i = 1, j = n / 2; i < n - 1; ++i) { if (i < j) swap(a[i], a[j]); int k = n / 2; while (j >= k) j -= k, k /= 2; if (j < k) j += k; } } void fft(vector& a, int flag) { int n = a.size(); bit_reverse(a); vector wn(n); wn[0] = 1; wn[1] = power_mod(G, flag == 1 ? (MOD - 1) / n : MOD - 1 - (MOD - 1) / n); for (int i = 2; i < n; ++i) wn[i] = (int64)wn[i - 1] * wn[1] % MOD; for (int k = 2; k <= n; k <<= 1) { for (int i = 0; i < n; i += k) { int wi = 0, step = n / k; for (int j = i; j < i + k / 2; ++j) { atom u = a[j]; atom v = (int64)wn[wi] * a[j + k / 2] % MOD; a[j] = (u + v) % MOD; a[j + k / 2] = (u + MOD - v) % MOD; wi += step; } } } if (flag < 0) { int64 inv_n = inv_mod(n); for (int i = 0; i < n; ++i) a[i] = a[i] * inv_n % MOD; } } namespace polynomial { vector mul(const vector& f, const vector& g, int cap = inf) { int n = f.size(), m = g.size(); int len = 1; while (len < n + m - 1) len <<= 1; vector x(len), y(len); copy(f.begin(), f.end(), x.begin()); copy(g.begin(), g.end(), y.begin()); fft(x, 1); fft(y, 1); for (int i = 0; i < len; ++i) x[i] = (int64)x[i] * y[i] % MOD; fft(x, -1); cap = min(cap, n + m - 1); x.resize(cap); return x; } vector differential(const vector& f) { int n = f.size(); vector ret(n); for (int i = 0; i < n - 1; ++i) ret[i] = (int64)f[i + 1] * (i + 1) % MOD; return ret; } void integral(vector& f) { int n = f.size(); for (int i = n - 1; i > 0; --i) f[i] = inv_mod(i) * f[i - 1] % MOD; f[0] = 0; } // g:=g*(2-f*g), n is power of 2 vector inverse(const vector& f) { int n = f.size(); if (n == 1) return {(int)inv_mod(f[0])}; vector f1(f.begin(), f.begin() + (n >> 1)); auto g = inverse(f1); g.resize(n); auto h = mul(f, g, n); h[0] = (2 + MOD - h[0]) % MOD; for (int i = 1; i < h.size(); ++i) h[i] = (MOD - h[i]) % MOD; return mul(h, g, n); } pair, vector> div(const vector& f, const vector& g) { int n = f.size(), m = g.size(); int k = n - m + 1; if (n < m) return make_pair(vector{0}, f); int len = 1; while (len < m) len <<= 1; vector fr(n), gr(len); copy(f.rbegin(), f.rend(), fr.begin()); copy(g.rbegin(), g.rend(), gr.begin()); auto h = inverse(gr); h = mul(fr, h); vector d(k); for (int i = 0; i < k; ++i) d[i] = h[k - 1 - i]; h = mul(g, d); vector r(m); for (int i = 0; i < m; ++i) r[i] = (f[i] + MOD - h[i]) % MOD; int deg_r = m - 1; while (deg_r && r[deg_r] == 0) --deg_r; r.resize(deg_r + 1); return make_pair(d, r); } int64 W; ii operator *(const ii& u, const ii& v) { return {((int64)u.first * v.first + (int64)u.second * v.second % MOD * W) % MOD, ((int64)u.first * v.second + (int64)u.second * v.first) % MOD}; } ii power_mod(ii a, int64 n) { ii ret = {1, 0}; for (; n; n >>= 1) { if (n & 1) ret = ret * a; a = a * a; } return ret; } int cipolla(int x) { int y; while (true) { y = rnd(MOD); W = ((int64)y * y % MOD + MOD - x) % MOD; if (::power_mod(W, (MOD - 1) / 2) > 1) break; } ii ret(y, 1); ret = power_mod(ret, (MOD + 1) / 2); return min(ret.first, MOD - ret.first); } // g:=(g+f/g)/2, n is power of 2 vector sqrt(const vector& f) { int n = f.size(); if (n == 1) return {cipolla(f[0])}; vector f1(f.begin(), f.begin() + (n >> 1)); auto g = sqrt(f1); g.resize(n); auto h = inverse(g); h = mul(f, h, n); int64 inv2 = inv_mod(2); for (int i = 0; i < n; ++i) g[i] = (g[i] + h[i]) * inv2 % MOD; return g; } // g=integral(f'/f), n is power of 2 vector log(const vector& f) { auto g = differential(f); auto h = inverse(f); auto ret = mul(g, h); ret.resize(f.size()); integral(ret); return ret; } // g:=g*(1-log(g)+f), n is power of 2 vector exp(const vector& f) { int n = f.size(); if (n == 1) return vector{1}; vector f1(f.begin(), f.begin() + (n >> 1)); auto g = exp(f1); g.resize(n); auto h = log(g); for (int i = 0; i < n; ++i) h[i] = ((i == 0) + f[i] + MOD - h[i]) % MOD; return mul(g, h, n); } } using namespace polynomial; const int N = 1e5 + 10; int a[N]; vector solve(int L, int R) { if (L + 1 == R) return {1, MOD - a[L]}; int mid = (L + R) / 2; return mul(solve(L, mid), solve(mid, R)); } int main() { int n, m; cin >> n >> m; for (int i = 0; i < n; ++i) cin >> a[i]; auto f = solve(0, n); trace(f); int len = 1; while (len <= m) len *= 2; f.resize(len); f = log(f); vector ret(m); for (int k = 1; k <= m; ++k) { ret[k - 1] = (MOD - 1LL * f[k] * k % MOD) % MOD; } out(ret); return 0; }