// #pragma GCC optimize("Ofast") // #pragma GCC target("sse4") #include using namespace std; #define GET_MACRO(_1, _2, _3, _4, NAME, ...) NAME #define __FOR3(i, a, n, inc) for(int i = (a); (inc) > 0 ? i < (n) : i >= (n); i += (inc)) #define __FOR2(i, a, n) __FOR3(i, a, n, 1) #define __FOR1(i, n) __FOR2(i, 0, n) #define __FOR0(n) __FOR1(_, n) #define FOR(...) GET_MACRO(__VA_ARGS__, __FOR3, __FOR2, __FOR1, __FOR0)(__VA_ARGS__) #define BOOST ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define ELO exit(0) #define ALL(a) (a).begin(), (a).end() #define SZ(a) (int)(a).size() #define TRAV(a, b) for (auto& a : b) #define REV(a) reverse(ALL(a)) #define SORT(a) sort(ALL(a)) #define SORTR(a) SORT(a), REV(a) #define PB push_back #define F first #define S second using ll = long long; using ld = long double; // 'long double' is 2.2 times slower than double using pii = pair; using pll = pair; using pld = pair; using vb = vector; using vi = vector; using vvi = vector; using vll = vector; using vvll = vector; using vpii = vector; using vpll = vector; using vld = vector; using vpld = vector; constexpr int MOD = 167772161; // 998244353 constexpr int INF = MOD; constexpr ll LLINF = 1e18; const ld PI = acos(-1); template inline bool setmin(T& a, T b) {if (a > b) return a = b, 1; return 0; } template inline bool setmax(T& a, T b) {if (a < b) return a = b, 1; return 0; } namespace input { template istream &operator>>(istream &os, vector & vec) { for (auto& u : vec) os >> u; return os; } template istream& operator>>(istream& os, pair& p) { return os >> p.first >> p.second; } template istream& operator>>(istream& os, array& a) { for (auto& u : a) os >> u; return os; } void re() {} template void re(T& x, args&... tail) { cin >> x; re(tail...); } } // namespace input using namespace input; namespace output { template ostream &operator<<(ostream &os, const vector & vec){for (const auto& u : vec) os << u << " "; return os; } template ostream& operator<<(ostream& os, const pair& p) { return os << p.first << " " << p.second; } template ostream &operator<<(ostream &os, set & con) { for (const auto& u : con) os << u << " "; return os; } template ostream& operator<<(ostream& os, array& a) { for (const auto& u : a) os << u << " "; return os; } void pr() {} template void pr(const T& x) { cout << x; } template void pr(const T& x, const args&... tail) { cout << x << " "; pr(tail...);} template void prs(const T& x) { cout << x << " "; } template void prs(const T& x, const args&... tail) { cout << x << " "; prs(tail...);} template void prln(const args&... tail) { pr(tail...); cout << "\n";} } // namespace output using namespace output; namespace pair_magic { #define PT1T2 pair #define TT1T2 template TT1T2 inline PT1T2 operator+(const PT1T2 &p1, const PT1T2 &p2) { return PT1T2(p1.first + p2.first, p1.second + p2.second); } TT1T2 inline PT1T2& operator+=(PT1T2 &p1, const PT1T2 &p2) { p1.first += p2.first, p1.second += p2.second; return p1; } TT1T2 inline PT1T2 operator-(const PT1T2 &p1, const PT1T2 &p2) { return PT1T2(p1.first - p2.first, p1.second - p2.second); } TT1T2 inline PT1T2& operator-=(PT1T2 &p1, const PT1T2 &p2) { p1.first -= p2.first, p1.second -= p2.second; return p1; } #undef PT1T2 #undef TT1T2 } using namespace pair_magic; namespace random_nsp { thread_local std::mt19937 gen{std::random_device{}()}; template T random(T min, T max){using dist = std::conditional_t::value, std::uniform_int_distribution, std::uniform_real_distribution>;return dist{min, max}(gen);} template T randomINT(T min, T max) { return std::uniform_int_distribution{min, max}(gen); } } using namespace random_nsp; namespace triple { #define TT1T2T3 template #define TRT1T2T3 triple TT1T2T3 struct triple { T1 a; T2 b; T3 c; triple() : a(T1()), b(T2()), c(T3()) {}; triple(T1 _a, T2 _b, T3 _c) :a(_a), b(_b), c(_c) {} }; TT1T2T3 bool operator<(const TRT1T2T3&t1, const TRT1T2T3&t2) { if (t1.a != t2.a)return t1.a < t2.a; else if (t1.b != t2.b)return t1.b < t2.b; else return t1.c < t2.c; } TT1T2T3 bool operator>(const TRT1T2T3&t1, const TRT1T2T3&t2) { if (t1.a != t2.a)return t1.a > t2.a; else if (t1.b != t2.b)return t1.b > t2.b; else return t1.c > t2.c; } TT1T2T3 bool operator==(const TRT1T2T3&t1, const TRT1T2T3&t2) { return (t1.a == t2.a && t1.b == t2.b && t1.c == t2.c); } TT1T2T3 inline istream& operator >> (istream& os, triple& t) { return os >> t.a >> t.b >> t.c; } TT1T2T3 ostream& operator << (ostream& os, const triple& t) { return os << t.a << " " << t.b << " " << t.c; } #undef TRT1T2T3 #undef TT1T2T3 using tri = triple; using trll = triple; using vtri = vector; using vtrll = vector; } using namespace triple; template T invGeneral(T a, T b) { // 0 < a < b, gcd(a,b) = 1 a %= b; if (a == 0) return b == 1 ? 0 : -1; T x = invGeneral(b, a); return x == -1 ? -1 : ((1-(ll)b * x) / a + b) % b; } template struct modular { T val; explicit operator T() const { return val; } modular() { val = 0; } modular(const ll& v) { val = (-MOD <= v && v <= MOD) ? v : v % MOD; if (val < 0) val += MOD; } friend ostream& operator<<(ostream& os, const modular& a) { return os << a.val; } friend void pr(const modular& a) { pr(a.val); } friend void re(modular& a) { ll x; re(x); a = modular(x); } friend bool operator==(const modular& a, const modular& b) { return a.val == b.val; } friend bool operator!=(const modular& a, const modular& b) { return !(a == b); } friend bool operator<(const modular& a, const modular& b) { return a.val < b.val; } modular operator-() const { return modular(-val); } modular& operator+=(const modular& m) { if ((val += m.val) >= MOD) val -= MOD; return *this; } modular& operator-=(const modular& m) { if ((val -= m.val) < 0) val += MOD; return *this; } modular& operator*=(const modular& m) { val = (ll)val*m.val%MOD; return *this; } friend modular pow(modular a, ll p) { modular ans = 1; for (; p; p /= 2, a *= a) if (p&1) ans *= a; return ans; } friend modular inv(const modular& a) { auto i = invGeneral(a.val,MOD); assert(i != -1); return i; } // equivalent to return exp(b,MOD-2) if MOD is prime modular& operator/=(const modular& m) { return (*this) *= inv(m); } friend modular operator+(modular a, const modular& b) { return a += b; } friend modular operator-(modular a, const modular& b) { return a -= b; } friend modular operator*(modular a, const modular& b) { return a *= b; } friend modular operator/(modular a, const modular& b) { return a /= b; } }; using mi = modular; using pmi = pair; using vmi = vector; using vpmi = vector; namespace debug { template < typename _T > inline void _debug(const char *s, _T x) { cerr << s << " = " << x << "\n"; } template < typename _T, typename... args > void _debug(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _debug(s + 1, a...); } #if defined(LOCAL) && 1 #define debug(...) _debug(#__VA_ARGS__, __VA_ARGS__) #define cerr cout #else #define debug(...) 1999 #define cerr if(0) cout #endif } // namespace debug using namespace debug; ///____________CODE____________/// const int N = 401; int n, k; int W[N]; mi dp[2][N][N][N]; void gowno(int d, int idx) { FOR(cnt, n + 1) { FOR(w, k + 1) { prs(dp[d][idx][cnt][w]); } prln(); } } void calc(int d) { auto DP = dp[d]; DP[0][0][0] = 1; FOR(i, 0, n) { FOR(cnt, i + 1) { FOR(w, k + 1) { DP[i + 1][cnt][w] = DP[i][cnt][w]; } } FOR(cnt, i + 1) { FOR(w, k + 1) { if (w + W[i] > k) continue; DP[i + 1][cnt + 1][w + W[i]] += DP[i][cnt][w]; } } } } const int mod = MOD; //119 * (1<<23) + 1 const int root = 243; //31 const int root_pw = 1 << 25; //1<<23 int egcd(int a, int b, int& x, int& y) { if (a == 0) { x = 0; y = 1; return b; } int x1, y1; int d = egcd(b % a, a, x1, y1); x = y1 - (b / a) * x1; y = x1; return d; } int inverse(int a, int mod = MOD) { int x, y; int g = egcd(a, mod, x, y); if (g != 1) { assert(0); } else { x = (x % mod); if (x < 0) x += mod; } return x; } const int root_1 = inverse(root, mod); //root ^ -1 void fft(vector & a, bool invert) { int n = a.size(); for (int i = 1, j = 0; i < n; i++) { int bit = n >> 1; for (; j & bit; bit >>= 1) j ^= bit; j ^= bit; if (i < j) swap(a[i], a[j]); } for (int len = 2; len <= n; len <<= 1) { int wlen = invert ? root_1 : root; for (int i = len; i < root_pw; i <<= 1) wlen = (int)(1LL * wlen * wlen % mod); for (int i = 0; i < n; i += len) { int w = 1; for (int j = 0; j < len / 2; j++) { int u = a[i + j], v = (int)(1LL * a[i + j + len / 2] * w % mod); a[i + j] = u + v < mod ? u + v : u + v - mod; a[i + j + len / 2] = u - v >= 0 ? u - v : u - v + mod; w = (int)(1LL * w * wlen % mod); } } } if (invert) { int n_1 = inverse(n, mod); for (int & x : a) x = (int)(1LL * x * n_1 % mod); } } vector multiply(vector const& a, vector const& b) { vector fa(a.begin(), a.end()), fb(b.begin(), b.end()); int n = 1; while (n < a.size() + b.size()) n <<= 1; fa.resize(n); fb.resize(n); fft(fa, false); fft(fb, false); for (int i = 0; i < n; i++) fa[i] = (1ll * fa[i] * fb[i]) % mod; fft(fa, true); return fa; } void calc2(int idx) { const int XD = 805; vi l(XD * 405); vi r(XD * 405); FOR(w, k + 1) { FOR(cnt, idx + 1) { l[w * (XD - 3) + cnt] = dp[0][idx][cnt][w].val; } } FOR(w, k + 1) { FOR(cnt, n - idx) { r[w * (XD - 3) + cnt] = dp[1][n - 1 - idx][cnt][w].val; } } auto res = multiply(l, r); vmi result(n); FOR(w, k - W[idx] + 1, k + 1) { FOR(cnt, n) { result[cnt] += res[w * (XD - 3) + cnt]; } } FOR(i, 1, n) { cout << result[i] << " "; } cout << "\n"; } int main() { BOOST; re(n, k); FOR(i, n) re(W[i]); FOR(d, 2) { calc(d); reverse(W, W + n); } FOR(i, n) { calc2(i); } }