#include #include #include #include #include #include #define ALL -1 #define MAX_GANGSTERS 401 #define MOD 167772161 using namespace std; int r[MAX_GANGSTERS+1][MAX_GANGSTERS+1]; void insert_weight(unordered_map> &dict, int k, int v, int g) { if (dict.find(k) == dict.end()) { dict[k] = unordered_map(); } if (dict[k].find(g) == dict[k].end()) { dict[k][g] = v; } else { dict[k][g] = (dict[k][g] + v) % MOD; } if (dict[k].find(ALL) == dict[k].end()) { dict[k][ALL] = v; } else { dict[k][ALL] = ( dict[k][ALL] + v) % MOD; } } int main() { memset(r, 0, sizeof(r)); int gangsters, max_weight, num, sum, val; vector begin_weights; vector> weights; cin >> gangsters >> max_weight; for (int i = 0; i < gangsters; ++i) { cin >> num; begin_weights.emplace_back(num); weights.emplace_back(make_pair(num, i)); } sort(weights.begin(), weights.end()); vector smaller_combinations_weights, bigger_combiations_weights, even_bigger_combiations_weights; unordered_map> smaller_combinations_dict, bigger_combinations_dict, even_bigger_combinations_dict; for (int i = 0; i < weights.size(); ++i) { insert_weight(smaller_combinations_dict, weights[i].first, 1, weights[i].second); smaller_combinations_weights.emplace_back(weights[i].first); } bigger_combiations_weights = smaller_combinations_weights; bigger_combinations_dict = smaller_combinations_dict; for (int i = 1; i <= gangsters - 1; ++i) { // for (const std::pair> &p : bigger_combinations_dict) { // std::cout << p.first << endl; // for (const std::pair &p2 : p.second) { // std::cout << p2.first << " " << p2.second << endl; // } // } for (int j = 0; j < gangsters; ++j) { auto upper = lower_bound(bigger_combiations_weights.begin(), bigger_combiations_weights.end(), (max_weight - begin_weights[j]) + 1); auto ind = upper - bigger_combiations_weights.begin(); // std::cout << (max_weight - begin_weights[j] + 1) << " " << begin_weights[j] << " " << ind << std::endl; int w, me; // std::cout << "to je " << j << endl; if (ind < bigger_combiations_weights.size()) { w = bigger_combiations_weights[ind]; sum = 0; for (int k = w; k <= max_weight; ++k) { if (bigger_combinations_dict.find(k) != bigger_combinations_dict.end()) { me = (bigger_combinations_dict[k].find(j) == bigger_combinations_dict[k].end()) ? 0 : (bigger_combinations_dict[k][j] * (i)); // std::cout << bigger_combinations_dict[k][ALL] << " " << me << std::endl; val = (bigger_combinations_dict[k][ALL] - me) / i; // std::cout << val << std::endl; sum = (sum + val) % MOD; } } // std::cout << j << " " << i << " " << sum << endl; r[j][i] = sum; } upper = upper_bound(bigger_combiations_weights.begin(), bigger_combiations_weights.end(), max_weight - begin_weights[j]); ind = upper - bigger_combiations_weights.begin(); if (ind > 0) { w = bigger_combiations_weights[ind - 1]; // std::cout << (max_weight - begin_weights[j] + 1) << " " << begin_weights[j] << " " << ind << std::endl; for (int k = 1; k <= w; ++k) { if (begin_weights[j] + k > max_weight) { break; } if (bigger_combinations_dict.find(k) == bigger_combinations_dict.end()) { continue; } auto me = (bigger_combinations_dict[k].find(j) == bigger_combinations_dict[k].end()) ? 0 : (bigger_combinations_dict[k][j] * (i)); if (me != bigger_combinations_dict[k][ALL] && even_bigger_combinations_dict.find(begin_weights[j] + k) == even_bigger_combinations_dict.end() && bigger_combinations_dict[k][ALL] - bigger_combinations_dict[k][j] > 0) { even_bigger_combiations_weights.emplace_back(begin_weights[j] + k); } // std::cout << j << " " << k << " " << bigger_combinations_dict[k][ALL] - (bigger_combinations_dict[k][j] * (i + 1)) << endl; if (me != bigger_combinations_dict[k][ALL] ) { insert_weight(even_bigger_combinations_dict, begin_weights[j] + k, (bigger_combinations_dict[k][ALL] - me) / i, j); } } } } bigger_combinations_dict = even_bigger_combinations_dict; bigger_combiations_weights = even_bigger_combiations_weights; even_bigger_combinations_dict.clear(); even_bigger_combiations_weights.clear(); sort(bigger_combiations_weights.begin(), bigger_combiations_weights.end()); } for (int i = 0; i < gangsters; ++i) { for (int j = 0; j < gangsters - 1; ++j) { std::cout << r[i][j+1] << " "; } std::cout << endl; } return 0; }