// PA2025 runda 5C - https://sio2.mimuw.edu.pl/c/pa-2025-1/p/tur/ //-std=c++20 #include<iostream> #include<vector> #include<algorithm> #include<list> using namespace std; #define max(a, b) ((a) > (b) ? (a) : (b)) vector<u_int64_t> combinations; void init_combinations() { u_int64_t max{11'000}; combinations.resize(max); //i=0 -> n=3 u_int64_t x{3}; u_int64_t comb{1}; combinations[0] = 1; for (int i = 1; i < max; ++i) { x++; comb *= x; comb /= x - 3; combinations[i] = comb; } } u_int64_t choose_2_from_n(u_int64_t n) { if (n < 2)return 0; u_int64_t kf{2}; u_int64_t nf{n * (n - 1)}; return nf / kf; } u_int64_t choose_3_from_n(u_int64_t n) { u_int64_t kf{6}; u_int64_t nf{n * (n - 1) * (n - 2)}; return nf / kf; } void submain() { u_int32_t n; cin >> n; list<u_int64_t> houses; u_int64_t sum{0}; for (int i = 0; i < n; i++) { u_int64_t item; cin >> item; sum += item; if (item > 0) { houses.push_back(item); } } auto it = lower_bound(combinations.begin(), combinations.end(), sum); auto peoples = it - combinations.begin() + 3; bool fine = true; //list<u_int64_t> rs; do { //rs.clear(); fine = true; u_int64_t r{2}; vector<u_int64_t> rs; rs.resize(peoples - 1); for (int i = 0; i < peoples - 1; i++) { rs[i] = choose_2_from_n(i + 2) * (peoples - (i + 2)) + choose_3_from_n(i + 2); } auto h_it = houses.begin(); // szukamy takiego minimalnego r, żeby (r po 2)*(peoples-r)>=h_it int index = lower_bound(rs.begin(), rs.end(), *h_it) - rs.begin(); r = max(r, index + 2); while (++h_it != houses.end()) { //sprawdz drugą stronę, czy pozostałych wystarczy if (r * choose_2_from_n(peoples - r) + choose_3_from_n(peoples - r) < *h_it) { // za mało ludzi, od nowa peoples++; fine = false; break; } else { r++; // skoro jest non zero to co najmniej 1 osoba musiala tam mieszkac index = lower_bound(rs.begin(), rs.end(), *h_it) - rs.begin(); r = max(r, index + 2); } //rs.push_back(r); } } while (!fine); //for (const auto &r_value: rs) { // cerr << r_value << ' '; //} cout << peoples << '\n'; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); init_combinations(); int t; cin >> t; for (int i = 0; i < t; i++) { submain(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | // PA2025 runda 5C - https://sio2.mimuw.edu.pl/c/pa-2025-1/p/tur/ //-std=c++20 #include<iostream> #include<vector> #include<algorithm> #include<list> using namespace std; #define max(a, b) ((a) > (b) ? (a) : (b)) vector<u_int64_t> combinations; void init_combinations() { u_int64_t max{11'000}; combinations.resize(max); //i=0 -> n=3 u_int64_t x{3}; u_int64_t comb{1}; combinations[0] = 1; for (int i = 1; i < max; ++i) { x++; comb *= x; comb /= x - 3; combinations[i] = comb; } } u_int64_t choose_2_from_n(u_int64_t n) { if (n < 2)return 0; u_int64_t kf{2}; u_int64_t nf{n * (n - 1)}; return nf / kf; } u_int64_t choose_3_from_n(u_int64_t n) { u_int64_t kf{6}; u_int64_t nf{n * (n - 1) * (n - 2)}; return nf / kf; } void submain() { u_int32_t n; cin >> n; list<u_int64_t> houses; u_int64_t sum{0}; for (int i = 0; i < n; i++) { u_int64_t item; cin >> item; sum += item; if (item > 0) { houses.push_back(item); } } auto it = lower_bound(combinations.begin(), combinations.end(), sum); auto peoples = it - combinations.begin() + 3; bool fine = true; //list<u_int64_t> rs; do { //rs.clear(); fine = true; u_int64_t r{2}; vector<u_int64_t> rs; rs.resize(peoples - 1); for (int i = 0; i < peoples - 1; i++) { rs[i] = choose_2_from_n(i + 2) * (peoples - (i + 2)) + choose_3_from_n(i + 2); } auto h_it = houses.begin(); // szukamy takiego minimalnego r, żeby (r po 2)*(peoples-r)>=h_it int index = lower_bound(rs.begin(), rs.end(), *h_it) - rs.begin(); r = max(r, index + 2); while (++h_it != houses.end()) { //sprawdz drugą stronę, czy pozostałych wystarczy if (r * choose_2_from_n(peoples - r) + choose_3_from_n(peoples - r) < *h_it) { // za mało ludzi, od nowa peoples++; fine = false; break; } else { r++; // skoro jest non zero to co najmniej 1 osoba musiala tam mieszkac index = lower_bound(rs.begin(), rs.end(), *h_it) - rs.begin(); r = max(r, index + 2); } //rs.push_back(r); } } while (!fine); //for (const auto &r_value: rs) { // cerr << r_value << ' '; //} cout << peoples << '\n'; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); init_combinations(); int t; cin >> t; for (int i = 0; i < t; i++) { submain(); } } |