// 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(); } } |
English