#include using namespace std; int n, k; const int N = 401, K = 401; const int M = 167772161; int w[N]; int d[N][N]; struct pair_hash { template std::size_t operator () (const std::pair &p) const { auto h1 = std::hash{}(p.first); auto h2 = std::hash{}(p.second); // Mainly for demonstration purposes, i.e. works but is overly simple // In the real world, use sth. like boost.hash_combine return h1 ^ h2; } }; using umap = std::unordered_map, int, pair_hash>; inline void print(umap &mapa) { for (auto el : mapa) { cout << "<" << el.first.first << ", " << el.first.second << "> " << el.second << " " << " | "; } cout << endl << endl; } inline umap divide(int i, int start, int finish) { umap ans; if (start > finish) return ans; if (start == finish && start != i) { if (ans.count(make_pair(1, w[start]))) ans[make_pair(1, w[start])] += 1; else ans[make_pair(1, w[start])] = 1; return ans; } if (start == finish && start == i) return ans; int middle = (start + finish) / 2; umap lft = divide(i, start, middle); umap rght = divide(i, middle + 1, finish); for (auto l : lft) { ans[l.first] += l.second; } for (auto r : rght) { ans[r.first] += r.second; } for (auto l : lft) { for (auto r : rght) { if (l.first.second + r.first.second <= k) { int new_cnt = l.first.first + r.first.first; int new_sum = l.first.second + r.first.second; ans[make_pair(new_cnt, new_sum)] = (ans[make_pair(new_cnt, new_sum)] + (l.second * r.second) % M) % M; } } } return ans; } int main() { cin >> n >> k; for (int i = 0; i < n; ++i) { cin >> w[i]; } for (int i = 0; i < n; ++i) { umap lft = divide(i, 0, n - 1); for (auto el : lft) { if (el.first.second > k - w[i]) { d[i][el.first.first] = (d[i][el.first.first] + el.second) % M; } } for (int j = 1; j < n; ++j) { cout << d[i][j] << " "; } cout << endl; } }