#include // #include using namespace std; #if __cplusplus >= 202002L using namespace numbers; #endif // Given a set of items where i-th item has non-negative weight w[i], // find a subset S such that \sum_{i \in S} w[i] <= threshold and \sum_{i \in S} w[i] is maximized struct subset_sum{ vector _pref; vector> _dp; vector>> _prev; // w[i] < weight_bound // O(n * bound) void run_for_bounded_weight(const vector &w, int weight_bound, int threshold){ assert(weight_bound > 0 && threshold >= 0); for(auto x: w) assert(0 <= x && x < weight_bound); int n = (int)w.size(); _pref = {0}; while((int)_pref.size() - 1 < n && _pref.back() + w[(int)_pref.size() - 1] <= threshold) _pref.push_back(_pref.back() + w[(int)_pref.size() - 1]); const int cut = (int)_pref.size() - 1; if(n == cut){ subset_weight = _pref[n]; in_subset.assign(n, true); subset.resize(n); iota(subset.begin(), subset.end(), 0); return; } _dp.assign(n - cut + 1, vector(weight_bound << 1)); _prev.assign(n - cut + 1, vector>(weight_bound << 1, {-1, -1})); fill(_dp[0].begin() + weight_bound, _dp[0].end(), 0); _dp[0][weight_bound - 1] = cut + 1; for(auto x = weight_bound - 1; x >= 0; -- x) if(_dp[0][x]) for(auto l = _dp[0][x] - 1; l >= 1; -- l){ if(x >= w[l - 1] && _dp[0][x - w[l - 1]] < l){ _dp[0][x - w[l - 1]] = l; _prev[0][x - w[l - 1]] = {0, x}; } } for(auto r = 1; r <= n - cut; ++ r) for(auto x = 2 * weight_bound - 1; x >= 0; -- x){ if(_dp[r][x] < _dp[r - 1][x]){ _dp[r][x] = _dp[r - 1][x]; _prev[r][x] = {r - 1, x}; } if(x >= w[cut + r - 1] && _dp[r][x] < _dp[r - 1][x - w[cut + r - 1]]){ _dp[r][x] = _dp[r - 1][x - w[cut + r - 1]]; _prev[r][x] = {r - 1, x - w[cut + r - 1]}; } for(auto l = _dp[r][x] - 1; l >= max(1, _dp[r - 1][x]); -- l) if(x >= w[l - 1] && _dp[r][x - w[l - 1]] < l){ _dp[r][x - w[l - 1]] = l; _prev[r][x - w[l - 1]] = {r, x}; } } subset_weight = threshold; while(!_dp[n - cut][subset_weight - _pref.back() + weight_bound - 1]) -- subset_weight; in_subset.assign(n, false); fill(in_subset.begin(), in_subset.begin() + cut, true); for(auto r = n - cut, weight = subset_weight - _pref.back() + weight_bound - 1; ; ){ auto [nr, nweight] = _prev[r][weight]; if(!~nr) break; if(r == nr) in_subset[_dp[r][weight] - 1] = false; else if(weight != nweight) in_subset[cut + r - 1] = true; r = nr, weight = nweight; } subset.clear(); for(auto i = 0; i < n; ++ i) if(in_subset[i]) subset.push_back(i); } // O(n * log(\sum{w}) + SZ * sqrt(\sum{w}) / bit_width) template void run_for_small_total_weight(const vector &w, int threshold){ assert(threshold >= 0 && threshold < SZ); int n = (int)w.size(); map>> mp; for(auto i = 0; i < (int)w.size(); ++ i) mp[w[i]].push_back({i}); vector>> ordered_pool; while(!mp.empty()){ int weight = mp.begin()->first; auto &from = mp.begin()->second; if((int)from.size() >= 3){ auto &to = mp[weight << 1]; while((int)from.size() >= 3){ next(from.begin())->splice(next(from.begin())->begin(), from.front()); from.pop_front(); to.push_back(move(from.front())); from.pop_front(); } } for(; !from.empty(); from.pop_front()) ordered_pool.push_back({weight, move(from.front())}); mp.erase(mp.begin()); } vector first_appear(threshold + 1, -1); bitset dp{}; dp[0] = true; for(auto i = 0; i < (int)ordered_pool.size(); ++ i){ int weight = ordered_pool[i].first; auto dp_next = dp | dp << weight; auto dif = dp ^ dp_next; for(auto x = dif._Find_first(); x <= threshold; x = dif._Find_next(x)) first_appear[x] = i; dp = dp_next; } subset_weight = threshold; while(!dp[subset_weight]) -- subset_weight; in_subset.assign(n, false); subset.clear(); for(auto weight = subset_weight; weight; ){ int i = first_appear[weight]; for(auto ind: ordered_pool[i].second){ in_subset[ind] = true; subset.push_back(ind); } weight -= ordered_pool[i].first; } } int subset_weight; vector in_subset, subset; }; int main(){ cin.tie(0)->sync_with_stdio(0); cin.exceptions(ios::badbit | ios::failbit); auto __solve_tc = [&](auto __tc_num)->int{ int n; cin >> n; if(n * (n + 1) / 2 & 1){ cout << "-1\n"; return 0; } subset_sum ss; vector a(n); iota(a.begin(), a.end(), 1); ss.run_for_small_total_weight<10001>(a, n * (n + 1) / 4); ranges::copy(ss.in_subset, ostream_iterator(cout, "")); cout << "\n"; return 0; }; int __tc_cnt; cin >> __tc_cnt; for(auto __tc_num = 0; __tc_num < __tc_cnt; ++ __tc_num){ __solve_tc(__tc_num); } return 0; } /* */