結果
問題 | No.5020 Averaging |
ユーザー |
![]() |
提出日時 | 2024-02-25 17:24:51 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 914 ms / 1,000 ms |
コード長 | 55,648 bytes |
コンパイル時間 | 4,991 ms |
コンパイル使用メモリ | 260,008 KB |
実行使用メモリ | 26,676 KB |
スコア | 29,359,140 |
最終ジャッジ日時 | 2024-02-25 17:25:45 |
合計ジャッジ時間 | 53,178 ms |
ジャッジサーバーID (参考情報) |
judge11 / judge13 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
#ifdef ONLINE_JUDGE#define NDEBUG#pragma GCC target("avx2")#pragma GCC optimize("O3")#pragma GCC optimize("unroll-loops")#else#undef NDEBUG#endif#include <algorithm>#include <array>#include <bitset>#include <cassert>#include <chrono>#include <cmath>#include <complex>#include <concepts>#include <cstdio>#include <cstdlib>#include <cstring>#include <fstream>#include <functional>#include <iostream>#include <limits>#include <map>#include <memory>#include <mutex>#include <numeric>#include <optional>#include <queue>#include <ranges>#include <set>#include <sstream>#include <stack>#include <string>#include <thread>#include <tuple>#include <unordered_map>#include <unordered_set>#include <utility>#include <vector>namespace shr {namespace basic {using namespace std;using uchar = unsigned char;using uint = unsigned int;using ushort = unsigned short;using ull = unsigned long long;using ll = long long;using pii = pair<int, int>;using pdi = pair<double, int>;template <class T>concept printable = requires(T t, ostream& out) { out << t; };int len(const string& a) {return (int) a.length();}template <class T>int len(const vector<T>& a) {return (int) a.size();}template <class T>int len(const set<T>& a) {return (int) a.size();}template <class T>int len(const deque<T>& a) {return (int) a.size();}template <class T>int len(const priority_queue<T>& a) {return (int) a.size();}template <class T, int N>int len(const T (&a)[N]) {return N;}template <class T, int N>void clear_with(T (&a)[N], int val) {memset(a, val, sizeof(a));}template <totally_ordered T>bool update_min(T candidate, T& current_min) {if (candidate < current_min) {current_min = candidate;return true;}return false;}template <totally_ordered T>bool update_min_eq(T candidate, T& current_min) {if (candidate <= current_min) {current_min = candidate;return true;}return false;}template <totally_ordered T>bool update_max(T candidate, T& current_max) {if (candidate > current_max) {current_max = candidate;return true;}return false;}template <totally_ordered T>bool update_max_eq(T candidate, T& current_max) {if (candidate >= current_max) {current_max = candidate;return true;}return false;}template <class T>string tos(T a) {return to_string(a);}template <printable T>string tos(T a) {ostringstream os;os << a;return os.str();}constexpr double linearstep(double edge0, double edge1, double t) {return clamp((t - edge0) / (edge1 - edge0), 0.0, 1.0);}constexpr double smoothstep(double edge0, double edge1, double t) {t = linearstep(edge0, edge1, t);return t * t * (3 - 2 * t);}double exp_interp(double from, double to, double t) {return pow(from, 1 - t) * pow(to, t);}} // namespace basicusing namespace basic;namespace timer {double time_scale = 1.0;// return in msint timer(bool reset = false) {static auto st = chrono::system_clock::now();if (reset) {st = chrono::system_clock::now();return 0;} else {auto en = chrono::system_clock::now();int elapsed = (int) chrono::duration_cast<chrono::milliseconds>(en - st).count();return (int) round(elapsed / time_scale);}}} // namespace timernamespace tracer {bool debug = true;template <class T>concept is_pair = requires(T t) {t.first;t.second;};template <class T>concept has_str = requires(T t) {{ t.str() } -> convertible_to<string>;};template <printable T>void tracen(T&& t) {if (!debug)return;cerr << t;}template <class T>requires(has_str<T> && !printable<T>)void tracen(T&& t) {if (!debug)return;cerr << t.str();}template <class T, class U>void tracen(pair<T, U>& t) { // <- ?????????????????????? need this for trace(<iterable of pairs>)if (!debug)return;cerr << "(";tracen(t.first);cerr << ", ";tracen(t.second);cerr << ")";}template <class T, class U>void tracen(pair<T, U>&& t) { // <- ?????????????????????? need this for trace(make_pair(1, 2))if (!debug)return;cerr << "(";tracen(t.first);cerr << ", ";tracen(t.second);cerr << ")";}template <class T>requires(!printable<T>)void tracen(T&& t) {if (!debug)return;bool first = true;auto from = t.begin();auto until = t.end();cerr << "{";while (from != until) {if (first) {first = false;} else {cerr << ", ";}tracen(*from);from++;}cerr << "}";}template <class T, int N>requires(!same_as<decay_t<T>, char>)void tracen(T (&a)[N]) {if (!debug)return;cerr << "{";for (int i = 0; i < N; i++) {if (i > 0)cerr << ", ";tracen(a[i]);}cerr << "}";}template <class T1, class T2, class... Rest>void tracen(T1&& t1, T2&& t2, Rest&&... rest) {if (!debug)return;tracen(forward<T1>(t1));tracen(forward<T2>(t2), forward<Rest>(rest)...);}void trace() {if (!debug)return;cerr << endl;}template <class T, class... Rest>void trace(T&& t, Rest&&... rest) {if (!debug)return;tracen(forward<T>(t), forward<Rest>(rest)...);cerr << endl;}template <class T>requires(!printable<T>)void trace2d(T&& t, int h, int w) {if (!debug)return;bool first = true;auto from = t.begin();auto until = t.end();for (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {if (j > 0)tracen(" ");tracen(*from);from++;if (j == w - 1)trace();}}}template <class T, int N>requires(!same_as<decay_t<T>, char>)void trace2d(T (&a)[N], int h, int w) {if (!debug)return;int idx = 0;for (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {if (j > 0)tracen(" ");tracen(a[idx]);idx++;if (j == w - 1)trace();}}}} // namespace tracerusing namespace tracer;namespace random {class rngen {public:rngen() {}rngen(int s) {seed(s);}ull get_state() {return state;}void set_state(ull state) {this->state = state;}void seed(int s) {state = s + INCR;next32();}int next_int() {return next31();}int next_int(int mod) {assert(mod > 0);return (int) ((ull) next31() * mod >> 31);}int next_int(int min, int max) {return min + next_int(max - min + 1);}uint next_uint() {return next32();}ull next_ull() {return (ull) next32() << 32 | next32();}double next_float() {return (double) next31() / 0x80000000;}double next_float(double min, double max) {return min + next_float() * (max - min);}double next_normal() {return sqrt(-2 * log(next_float())) * cos(6.283185307179586 * next_float());}double next_normal(double mean, double sigma) {return mean + next_normal() * sigma;}private:static constexpr ull MULT = 0x8b46ad15ae59daadull;static constexpr ull INCR = 0xf51827be20401689ull;ull state = (ull) chrono::duration_cast<chrono::nanoseconds>(chrono::system_clock::now().time_since_epoch()).count();uint next32() {uint r = (uint) (state >> 59);state = state * MULT + INCR;state ^= state >> 18;uint t = (uint) (state >> 27);return t >> r | t << (-r & 31);}int next31() {return (int) (next32() & 0x7fffffff);}};void random_permutation(int* a, int n, rngen& rng) {assert(n >= 0);if (n == 0)return;a[0] = 0;for (int i = 1; i < n; i++) {a[i] = i;swap(a[i], a[rng.next_int(i + 1)]);}}template <class RandomAccessContainer>auto& random_pick(RandomAccessContainer& c, rngen& rng) {return c[rng.next_int(len(c))];}template <class RandomAccessContainer>const auto& random_pick(const RandomAccessContainer& c, rngen& rng) {return c[rng.next_int(len(c))];}template <class T, int N>T& random_pick(T (&c)[N], rngen& rng) {return c[rng.next_int(N)];}template <class T, int N>const T& random_pick(const T (&c)[N], rngen& rng) {return c[rng.next_int(N)];}} // namespace randomusing namespace random;namespace ds {// random access: O(1)// push: O(1)// insert: n/a// erase by position: O(1)// erase by element: n/a// max size: fixedtemplate <class T, int N>class fast_vector {private:T data[N];int num = 0;public:using iterator = T*;using const_iterator = const T*;iterator begin() {return data;}iterator end() {return data + num;}const_iterator begin() const {return data;}const_iterator end() const {return data + num;}void push_back(T a) {assert(num < N);data[num++] = a;}template <class... Args>void emplace_back(Args&&... args) {push_back(T(forward<Args>(args)...));}void erase(iterator where) {assert(where >= begin() && where < end());*where = data[--num];}void pop_back() {assert(num > 0);num--;}T& operator[](int i) {assert(i >= 0 && i < num);return data[i];}const T& operator[](int i) const {assert(i >= 0 && i < num);return data[i];}int size() const {return num;}};// random access: O(1)// push: O(1)// insert: n/a// erase: n/a// reallocation: nevertemplate <class T, int UnitBits = 20>class increasing_vector {private:static constexpr int UNIT_SIZE = 1 << UnitBits;static constexpr int UNIT_MASK = UNIT_SIZE - 1;T** packs;int num_packs = 0;int num_total = 0;public:increasing_vector(const increasing_vector& vec) = delete;increasing_vector& operator=(const increasing_vector& vec) = delete;increasing_vector() : packs(new T*[65536]) {}~increasing_vector() {for (int i = 0; i < num_packs; i++) {delete[] packs[i];}delete[] packs;}T* next_pointer() {if ((num_total++ & UNIT_MASK) == 0) {packs[num_packs++] = new T[UNIT_SIZE];}return &(*this)[num_total - 1];}void push_back(T a) {*next_pointer() = a;}template <class... Args>void emplace_back(Args&&... args) {push_back(T(forward<Args>(args)...));}T& operator[](int i) {assert(i >= 0 && i < num_total);return packs[i >> UnitBits][i & UNIT_MASK];}const T& operator[](int i) const {assert(i >= 0 && i < num_total);return packs[i >> UnitBits][i & UNIT_MASK];}int size() const {return num_total;}};// random access: O(1)// insert: O(1)// erase: O(1)// check: O(1)// max value: fixedtemplate <int N>class fast_iset {private:int data[N];int indices[N];int num = 0;public:using iterator = int*;using const_iterator = const int*;fast_iset() {memset(indices, -1, sizeof(indices));}iterator begin() {return data;}iterator end() {return data + num;}const_iterator begin() const {return data;}const_iterator end() const {return data + num;}bool insert(int a) {assert(a >= 0 && a < N);if (indices[a] != -1)return false;data[num] = a;indices[a] = num;num++;return true;}bool erase(int a) {assert(a >= 0 && a < N);int index = indices[a];if (index == -1)return false;assert(num > 0);indices[data[index] = data[--num]] = index;indices[a] = -1;return true;}void clear() {memset(indices, -1, sizeof(indices));num = 0;}bool contains(int a) const {return indices[a] != -1;}const int& operator[](int i) const {assert(i >= 0 && i < num);return data[i];}int size() const {return num;}bool empty() const {return num == 0;}};// insert: O(1)// get/set: O(1)// clear: O(1)// erase: n/atemplate <class T, int BucketBits = 20>class hash_imap {private:static constexpr int BUCKET_SIZE = 1 << BucketBits;static constexpr int BUCKET_MASK = BUCKET_SIZE - 1;ull* keys;T* values;ushort* access_time;ushort time = (ushort) -1;int num_elements = 0;int last_index = -1;ull last_key = -1;bool last_found = false;public:hash_imap(): keys(new ull[BUCKET_SIZE]), values(new T[BUCKET_SIZE]),access_time(new ushort[BUCKET_SIZE]) {}~hash_imap() {delete[] keys;delete[] values;delete[] access_time;}hash_imap(const hash_imap& map): keys(new ull[BUCKET_SIZE]), values(new T[BUCKET_SIZE]),access_time(new ushort[BUCKET_SIZE]) {memcpy(keys, map.keys, sizeof(ull[BUCKET_SIZE]));memcpy(values, map.values, sizeof(T[BUCKET_SIZE])); // can be potentially dangerous?memcpy(access_time, map.access_time, sizeof(ushort[BUCKET_SIZE]));time = map.time;num_elements = map.num_elements;last_index = map.last_index;last_key = map.last_key;last_found = map.last_found;}hash_imap& operator=(const hash_imap& map) {if (this == &map)return *this;delete[] keys;delete[] values;delete[] access_time;keys = new ull[BUCKET_SIZE];values = new T[BUCKET_SIZE];access_time = new ushort[BUCKET_SIZE];memcpy(keys, map.keys, sizeof(ull[BUCKET_SIZE]));memcpy(values, map.values, sizeof(T[BUCKET_SIZE])); // can be potentially dangerous?memcpy(access_time, map.access_time, sizeof(ushort[BUCKET_SIZE]));time = map.time;num_elements = map.num_elements;last_index = map.last_index;last_key = map.last_key;last_found = map.last_found;return *this;}void clear() {num_elements = 0;last_found = false;last_index = -1;if (++time == 0) {memset(access_time, 0, sizeof(ushort[BUCKET_SIZE]));time = 1;}}bool access(ull key) {last_key = key;last_index = (int) (key & BUCKET_MASK);bool debug = false;while (true) {if (access_time[last_index] != time) {return last_found = false;} else if (keys[last_index] == key) {return last_found = true;}last_index = (last_index + 1) & BUCKET_MASK;}}T get() const {assert(last_found);return values[last_index];}void set(T value) {assert(last_index != -1);access_time[last_index] = time;keys[last_index] = last_key;values[last_index] = value;num_elements += !last_found;assert(("bucket size is too small", num_elements < 0.85 * BUCKET_SIZE));}};// a bitset, but cooler than std::bitsettemplate <int Size>class rich_bitset {private:using word = ull;static_assert(has_single_bit(sizeof(word)));static constexpr int WORD_SHIFT = std::countr_zero(8 * sizeof(word));static constexpr int WORD_SIZE = 1 << WORD_SHIFT;static constexpr int WORD_MASK = WORD_SIZE - 1;static constexpr int NUM_WORDS = (Size + WORD_SIZE - 1) / WORD_SIZE;static constexpr int LAST_WORD = NUM_WORDS - 1;static constexpr word LAST_WORD_MASK =(Size & WORD_MASK) == 0 ? word(-1) : (word(1) << (Size & WORD_MASK)) - 1;#define REP_WORDS(i) for (int i = 0; i < NUM_WORDS; i++)#define REP_INNER_WORDS(i) for (int i = 0; i < NUM_WORDS - 1; i++)#define REP_WORDS_REV(i) for (int i = NUM_WORDS - 1; i >= 0; i--)#define REP_INNER_WORDS_REV(i) for (int i = NUM_WORDS - 2; i >= 0; i--)// [LAST_WORD] [LAST_WORD - 1] [...] [1] [0]// <- higher bits lower bits ->word data[NUM_WORDS];struct ref {rich_bitset<Size>& bs;const int pos;ref(rich_bitset<Size>& bs, int pos) : bs(bs), pos(pos) {}ref& operator=(bool val) {bs.set(pos, val);return *this;}operator bool() const {return bs.test(pos);}};void trim() {if constexpr ((Size & WORD_MASK) != 0) {data[LAST_WORD] &= LAST_WORD_MASK;}}public:rich_bitset(ull value = 0) {constexpr int BITS = sizeof(ull) * 8;for (int i = 0; i < (BITS + WORD_SIZE - 1) / WORD_SIZE; i++) {data[i] = value >> i * WORD_SIZE;}constexpr int OFFSET = (BITS + WORD_SIZE - 1) / WORD_SIZE;if constexpr (OFFSET < NUM_WORDS) {memset(data + OFFSET, 0, sizeof(word) * (NUM_WORDS - OFFSET));}}bool all() const {bool res = true;REP_INNER_WORDS(i) {res &= data[i] == word(-1);}res &= data[LAST_WORD] == LAST_WORD_MASK;return res;}bool none() const {bool res = true;REP_WORDS(i) {res &= data[i] == 0;}return res;}bool any() const {bool res = false;REP_WORDS(i) {res |= data[i] != 0;}return res;}int count() const {int res = 0;REP_WORDS(i) {res += popcount(data[i]);}return res;}int countr_zero() const {if constexpr (LAST_WORD == 0) {return std::countr_zero(word(data[LAST_WORD] | ~LAST_WORD_MASK));} else {int res = std::countr_zero(data[0]);int mask = -(res == WORD_SIZE); // continue adding if -1for (int i = 1; i < NUM_WORDS - 1; i++) {int count = std::countr_zero(data[i]);res += count & mask;mask &= -(count == WORD_SIZE);}int count = std::countr_zero(word(data[LAST_WORD] | ~LAST_WORD_MASK));res += count & mask;return res;}}int countl_zero() const {constexpr int LAST_WORD_SIZE = popcount(LAST_WORD_MASK);int res = std::countl_zero(word(~(~data[LAST_WORD] << (WORD_SIZE - LAST_WORD_SIZE))));int mask = -(res == LAST_WORD_SIZE); // continue adding if -1for (int i = NUM_WORDS - 2; i >= 0; i--) {int count = std::countl_zero(data[i]);res += count & mask;mask &= -(count == WORD_SIZE);}return res;}int countr_one() const {if constexpr (LAST_WORD == 0) {return std::countr_one(data[LAST_WORD]);} else {int res = std::countr_one(data[0]);int mask = -(res == WORD_SIZE); // continue adding if -1for (int i = 1; i < NUM_WORDS - 1; i++) {int count = std::countr_one(data[i]);res += count & mask;mask &= -(count == WORD_SIZE);}int count = std::countr_one(data[LAST_WORD]);res += count & mask;return res;}}int countl_one() const {constexpr int LAST_WORD_SIZE = popcount(LAST_WORD_MASK);int res = std::countl_one(word(data[LAST_WORD] << (WORD_SIZE - LAST_WORD_SIZE)));int mask = -(res == LAST_WORD_SIZE); // continue adding if -1for (int i = NUM_WORDS - 2; i >= 0; i--) {int count = std::countl_one(data[i]);res += count & mask;mask &= -(count == WORD_SIZE);}return res;}int size() const {return Size;}bool test(int pos) const {assert(pos >= 0 && pos < Size);return (data[pos >> WORD_SHIFT] >> (pos & WORD_MASK)) & 1;}uint to_uint() const {constexpr int BITS = sizeof(uint) * 8;for (int i = (BITS + WORD_SIZE - 1) / WORD_SIZE; i < NUM_WORDS; i++) {assert(("uint overflow", data[i] == 0));}if constexpr (WORD_SIZE > BITS) {assert(("uint overflow", (data[0] >> BITS) == 0));}uint res = (uint) data[0];for (int i = 1; i < (BITS + WORD_SIZE - 1) / WORD_SIZE && i < NUM_WORDS; i++) {res |= (uint) data[i] << i * WORD_SIZE;}return res;}ull to_ull() const {constexpr int BITS = sizeof(ull) * 8;for (int i = (BITS + WORD_SIZE - 1) / WORD_SIZE; i < NUM_WORDS; i++) {assert(("ull overflow", data[i] == 0));}if constexpr (WORD_SIZE > BITS) {assert(("ull overflow", (data[0] >> BITS) == 0));}ull res = (ull) data[0];for (int i = 1; i < (BITS + WORD_SIZE - 1) / WORD_SIZE && i < NUM_WORDS; i++) {res |= (ull) data[i] << i * WORD_SIZE;}return res;}rich_bitset& set(int pos, bool val = true) {assert(pos >= 0 && pos < Size);word bit = word(1) << (pos & WORD_MASK);if (val) {data[pos >> WORD_SHIFT] |= bit;} else {data[pos >> WORD_SHIFT] &= ~bit;}return *this;}rich_bitset& reset(int pos) {assert(pos >= 0 && pos < Size);return set(pos, false);}rich_bitset& flip(int pos) {assert(pos >= 0 && pos < Size);word bit = word(1) << (pos & WORD_MASK);data[pos >> WORD_SHIFT] ^= bit;return *this;}rich_bitset& set() {clear_with(data, -1);trim();return *this;}rich_bitset& reset() {clear_with(data, 0);return *this;}rich_bitset& flip() {REP_INNER_WORDS(i) {data[i] ^= word(-1);}data[LAST_WORD] ^= LAST_WORD_MASK;return *this;}rich_bitset& operator&=(const rich_bitset& a) {REP_WORDS(i) {data[i] &= a.data[i];}return *this;}rich_bitset& operator|=(const rich_bitset& a) {REP_WORDS(i) {data[i] |= a.data[i];}return *this;}rich_bitset& operator^=(const rich_bitset& a) {REP_WORDS(i) {data[i] ^= a.data[i];}return *this;}rich_bitset& operator<<=(int amount) {assert(amount >= 0 && amount < Size);int nw = amount >> WORD_SHIFT;if (nw > 0) {REP_WORDS_REV(i) {data[i] = i - nw < 0 ? 0 : data[i - nw];}}int nb = amount & WORD_MASK;if (nb) {for (int i = NUM_WORDS - 1; i > 0; i--) {data[i] = data[i] << nb | data[i - 1] >> (WORD_SIZE - nb);}data[0] <<= nb;}trim();return *this;}rich_bitset& operator>>=(int amount) {assert(amount >= 0 && amount < Size);int nw = amount >> WORD_SHIFT;if (nw > 0) {REP_WORDS(i) {data[i] = i + nw >= NUM_WORDS ? 0 : data[i + nw];}}int nb = amount & WORD_MASK;if (nb) {REP_INNER_WORDS(i) {data[i] = data[i] >> nb | data[i + 1] << (WORD_SIZE - nb);}data[LAST_WORD] >>= nb;}return *this;}rich_bitset& operator+=(const rich_bitset& a) {word carry = 0;REP_WORDS(i) {word l = data[i];word r = a.data[i];word sum = l + r;data[i] = sum + carry;carry = (sum < l) | (data[i] < sum);}trim();return *this;}rich_bitset& operator-=(const rich_bitset& a) {word carry = 1;REP_WORDS(i) {word l = data[i];word r = ~a.data[i];word sum = l + r;data[i] = sum + carry;carry = (sum < l) | (data[i] < sum);}trim();return *this;}rich_bitset& operator++() {word carry = 1;REP_WORDS(i) {word l = data[i];data[i] = l + carry;carry = (data[i] < l);}trim();return *this;}rich_bitset operator++(int) {rich_bitset res = *this;operator++();return res;}rich_bitset& operator--() {word carry = 0;REP_WORDS(i) {word l = data[i];data[i] = l - 1 + carry;carry = (l | carry) != 0;}trim();return *this;}rich_bitset operator--(int) {rich_bitset res = *this;operator--();return res;}rich_bitset operator~() const {rich_bitset res = *this;res.flip();return res;}friend rich_bitset operator&(const rich_bitset& a, const rich_bitset& b) {rich_bitset res = a;res &= b;return res;}friend rich_bitset operator|(const rich_bitset& a, const rich_bitset& b) {rich_bitset res = a;res |= b;return res;}friend rich_bitset operator^(const rich_bitset& a, const rich_bitset& b) {rich_bitset res = a;res ^= b;return res;}friend rich_bitset operator<<(const rich_bitset& a, int amount) {rich_bitset res = a;res <<= amount;return res;}friend rich_bitset operator>>(const rich_bitset& a, int amount) {rich_bitset res = a;res >>= amount;return res;}friend rich_bitset operator+(const rich_bitset& a, const rich_bitset& b) {rich_bitset res = a;res += b;return res;}friend rich_bitset operator-(const rich_bitset& a, const rich_bitset& b) {rich_bitset res = a;res -= b;return res;}friend bool operator==(const rich_bitset& a, const rich_bitset& b) {return memcmp(a.data, b.data, sizeof(a.data)) == 0;}friend bool operator!=(const rich_bitset& a, const rich_bitset& b) {return memcmp(a.data, b.data, sizeof(a.data)) != 0;}friend int operator<=>(const rich_bitset& a, const rich_bitset& b) {REP_WORDS_REV(i) {if (a.data[i] != b.data[i])return a.data[i] < b.data[i] ? -1 : 1;}return 0;}ref operator[](int pos) {return {*this, pos};}bool operator[](int pos) const {return test(pos);}string str() const {ostringstream oss;oss << *this;return oss.str();}friend ostream& operator<<(ostream& out, const rich_bitset& bs) {for (int i = Size - 1; i >= 0; i--) {out << (bs.test(i) ? '1' : '0');}return out;}#undef REP_WORDS#undef REP_INNER_WORDS#undef REP_WORDS_REV#undef REP_INNER_WORDS_REV};template <class T>class easy_stack {private:vector<T> data;public:auto begin() {return data.begin();}auto end() {return data.end();}auto begin() const {return data.begin();}auto end() const {return data.end();}void push_back(T a) {data.push_back(a);}template <class... Args>void emplace(Args&&... args) {data.emplace_back(forward<Args>(args)...);}T pop_back() {T res = data.back();data.pop_back();return res;}int size() const {return (int) data.size();}bool empty() const {return data.empty();}};template <int N>int len(const fast_iset<N>& a) {return a.size();}template <class T, int N>int len(const fast_vector<T, N>& a) {return a.size();}template <class T, int BucketBits>int len(const hash_imap<T, BucketBits>& a) {return a.size();}template <class T>int len(const easy_stack<T>& a) {return a.size();}} // namespace dsusing namespace ds;namespace beam_search {// (state) -> scoretemplate <class T, class State, class Score>concept get_score =totally_ordered<Score> && invocable<T, State&> && same_as<invoke_result_t<T, State&>, Score>;// (state, move) -> voidtemplate <class T, class State, class MoveId>concept apply_move =invocable<T, State&, MoveId> && same_as<invoke_result_t<T, State&, MoveId>, void>;// (state) -> voidtemplate <class T, class State>concept undo_move = invocable<T, State&> && same_as<invoke_result_t<T, State&>, void>;// (state) -> void// see also: add_candidatetemplate <class T, class State>concept enumerate_candidates = invocable<T, State&> && same_as<invoke_result_t<T, State&>, void>;// (turn) -> void// see also: candidates_to_filtertemplate <class T>concept filter_candidates = invocable<T, int> && same_as<invoke_result_t<T, int>, void>;template <class State, totally_ordered Score, class MoveId, MoveId UnusedMoveId, class CandidateData,class Direction = greater<Score>, int HashBucketBits = 20>class beam_search {private:struct candidate {int index; // index in orig_candidatesint parent;MoveId move_id;CandidateData data;ull hash;};struct orig_candidate {int parent;MoveId move_id;bool chosen;};Direction dir = {};int current_parent = 0;hash_imap<int, HashBucketBits> best_indices;bool enumerating = false;bool filtering = false;vector<candidate> candidates;vector<orig_candidate> orig_candidates;void clear_candidates() {candidates.clear();orig_candidates.clear();}public:Score best_score = 0;int max_turn = -1;beam_search() {}beam_search(Direction dir) : dir(dir) {}void add_candidate(MoveId move_id, CandidateData data, ull hash) {assert(("not enumerating now", enumerating));candidates.emplace_back((int) candidates.size(), current_parent, move_id, data, hash);orig_candidates.emplace_back(current_parent, move_id);}vector<candidate>& candidates_to_filter() {assert(("not filtering now", filtering));return candidates;}// CAUTION: not stabletemplate <predicate<candidate&, candidate&> CandidateDirection>void remove_duplicates(CandidateDirection candidate_direction) {assert(("not filtering now", filtering));best_indices.clear();int n = (int) candidates.size();for (int i = 0; i < n; i++) {candidate& cand = candidates[i];if (best_indices.access(cand.hash)) {int j = best_indices.get();candidate& cand2 = candidates[j];if (candidate_direction(cand, cand2)) {swap(candidates[i], candidates[j]);}swap(candidates[i], candidates[--n]);i--;} else {best_indices.set(i);}}candidates.resize(n);}template <get_score<State, Score> GetScore, apply_move<State, MoveId> ApplyMove,enumerate_candidates<State> EnumerateCandidates, filter_candidates FilterCandidates>vector<MoveId> run(const State& initial_state, GetScore get_score, ApplyMove apply_move,EnumerateCandidates enumerate_candidates, FilterCandidates filter_candidates) {struct node {State state;int history_index;};struct history {MoveId move_id;int parent;};vector<node> src;vector<node> dst;increasing_vector<history> hs;int turn = 0;// set initial statesrc.emplace_back(initial_state, -1);while (true) {int num_states = (int) src.size();clear_candidates();if (max_turn == -1 || turn < max_turn) {// enumerate candidatesenumerating = true;for (int i = 0; i < num_states; i++) {current_parent = i;enumerate_candidates(src[i].state);}enumerating = false;// filer candiadtesfiltering = true;filter_candidates(turn);filtering = false;}// check if finishedif (candidates.empty()) {assert(("no states at the end", num_states > 0));// pick the best statebest_score = get_score(src[0].state);int best_index = 0;for (int i = 1; i < num_states; i++) {Score score = get_score(src[i].state);if (dir(score, best_score)) {best_score = score;best_index = i;}}// restore movesvector<MoveId> res;int history_top = src[best_index].history_index;while (history_top != -1) {history& h = hs[history_top];res.push_back(h.move_id);history_top = h.parent;}reverse(res.begin(), res.end());return res;}// compute next statesdst.clear();for (const auto& cand : candidates) {const auto& src_node = src[cand.parent];dst.emplace_back(src_node.state, hs.size());apply_move(dst.back().state, cand.move_id);hs.emplace_back(cand.move_id, src_node.history_index);}src.swap(dst);turn++;}}template <get_score<State, Score> GetScore, apply_move<State, MoveId> ApplyMove,undo_move<State> UndoMove, enumerate_candidates<State> EnumerateCandidates,filter_candidates FilterCandidates>vector<MoveId> run_tree(const State& initial_state, GetScore get_score, ApplyMove apply_move,UndoMove undo_move, EnumerateCandidates enumerate_candidates,FilterCandidates filter_candidates) {constexpr MoveId UNDO = UnusedMoveId;struct tour {vector<MoveId> src;vector<MoveId> dst;void move(const MoveId& move_id) {dst.push_back(move_id);}int position() {return (int) dst.size();}void swap() {src.swap(dst);dst.clear();}} tour;vector<MoveId> global_path;vector<MoveId> path;vector<orig_candidate> leaves;State st = initial_state;int turn = 0;int level = 0;int next_start_pos = 0;auto global_move = [&](const MoveId& move_id) {apply_move(st, move_id);global_path.push_back(move_id);level++;};auto global_undo = [&]() {undo_move(st);global_path.pop_back();level--;};while (true) {bool has_next_turn = max_turn == -1 || turn < max_turn;// compute the next tourint pos = next_start_pos;int prev_root_level = level;int next_root_level = numeric_limits<int>::max();orig_candidate best_leaf = {-1, MoveId{}, false};enumerating = true;clear_candidates();if (turn == 0) {best_score = get_score(st);best_leaf.chosen = true;if (has_next_turn) {current_parent = tour.position();enumerate_candidates(st);}} else {for (const orig_candidate& leaf : leaves) {int parent_pos = leaf.parent;// visit the parent of the leaf nodeif (pos < parent_pos) {// visit the LCApath.clear();do {auto move = tour.src[pos++];if (move == UNDO) {if (path.empty()) {global_undo();tour.move(UNDO);next_root_level = min(next_root_level, level);} else {path.pop_back();}} else {path.push_back(move);}} while (pos < parent_pos);// go directly to the parentfor (auto move : path) {global_move(move);tour.move(move);}} // now we are at the parent of the leaf node// visit the leaf nodeapply_move(st, leaf.move_id);tour.move(leaf.move_id);Score score = get_score(st);if (!best_leaf.chosen || dir(score, best_score)) {best_score = score;best_leaf = leaf;}if (has_next_turn) {current_parent = tour.position();enumerate_candidates(st);}// leave the leaf nodeundo_move(st);tour.move(UNDO);}}next_root_level = min(next_root_level, level);enumerating = false;filtering = true;filter_candidates(turn);filtering = false;if (candidates.empty()) {assert(best_leaf.chosen);// undo to the root levelwhile (level > prev_root_level) {global_undo();}// visit the best leafpos = next_start_pos;while (pos < best_leaf.parent) {auto move = tour.src[pos++];if (move == UNDO) {global_undo();} else {global_move(move);}}if (best_leaf.parent != -1) {global_move(best_leaf.move_id);}return global_path;}// finalize the next tourtour.swap();turn++;// collect the next leaf nodes, in the original orderleaves.clear();for (const candidate& cand : candidates) {orig_candidates[cand.index].chosen = true;}for (const orig_candidate& cand : orig_candidates) {if (!cand.chosen)continue;leaves.push_back(cand);}// undo to the next root levelwhile (level > next_root_level) {global_undo();}// adjust the next starting positionnext_start_pos = next_root_level - prev_root_level;}}};class beam_width_manager {private:double prev_time = 0;double moving_average_time = 0;vector<double> progress_history;vector<double> time_history;vector<int> width_history;int last_width = 0;int count = 0;public:int window_size = 50;int default_width;beam_width_manager(int default_width) : default_width(default_width) {}int next(double progress, double time, double time_limit) {progress_history.push_back(progress);time_history.push_back(time);width_history.push_back(last_width);count++;if (count <= window_size) {return last_width = default_width;}int i1 = count - 1 - window_size;int i2 = count - 1;double progress_sum = progress_history[i2] - progress_history[i1];double time_sum = time_history[i2] - time_history[i1];if (progress_sum == 0 || time_sum == 0) {// window size is too smallwindow_size *= 2;return last_width = default_width;}int width_sum = 0;for (int i = i1 + 1; i <= i2; i++) {width_sum += width_history[i];}double progress_per_turn = progress_sum / window_size;double time_per_width = time_sum / width_sum;double left_time = time_limit - time;double left_progress = 1 - progress;if (left_time <= 0 || left_progress <= 0)return 1;double left_turn = left_progress / progress_per_turn;double left_time_per_turn = left_time / left_turn;double left_width_per_turn = left_time_per_turn / time_per_width;return last_width = round(left_width_per_turn);}void report(int actual_last_width) {last_width = actual_last_width;}};} // namespace beam_searchnamespace simulated_annealing {// (state) -> scoretemplate <class T, class State, class Score>concept get_score =totally_ordered<Score> && invocable<T, State&> && same_as<invoke_result_t<T, State&>, Score>;// (iter) -> progresstemplate <class T>concept update_progress = invocable<T, int> && same_as<invoke_result_t<T, int>, double>;// (state, tolerance) -> acceptedtemplate <class T, class State>concept try_transition =invocable<T, State&, double> && same_as<invoke_result_t<T, State&, double>, bool>;template <class State, totally_ordered Score, class Direction = greater<Score>>class simulated_annealing {private:Direction dir = {};public:int clock_interval = 10;double t_from = 100;double t_to = 0.01;double progress = 0;int num_iterations = 0;int num_acceptances = 0;int num_rejections = 0;bool use_linear_temp = false;Score best_score = 0;simulated_annealing() {}simulated_annealing(Direction dir) : dir(dir) {}template <get_score<State, Score> GetScore, update_progress UpdateProgress,try_transition<State> TryTransition>State run(const State& initial_state, rngen& rng, GetScore get_score,UpdateProgress update_progress, TryTransition try_transition,function<void(State&, Score, int, double)> best_updated = nullptr) {State state = initial_state;Score score = get_score(state);State best_state = state;best_score = score;num_iterations = 0;num_acceptances = 0;num_rejections = 0;int interval = clock_interval;progress = 0;double t = t_from;while (true) {if (--interval <= 0) {progress = update_progress(num_iterations);if (progress >= 1)break;t = use_linear_temp ? lerp(t_from, t_to, progress): exp_interp(t_from, t_to, progress);interval = clock_interval;}double tolerance = t * -log(rng.next_float());if (try_transition(state, tolerance)) {num_acceptances++;score = get_score(state);if (dir(score, best_score)) {best_state = state;best_score = score;if (best_updated) {best_updated(state, score, num_iterations, t);}}} else {num_rejections++;}num_iterations++;}return best_state;}};} // namespace simulated_annealingnamespace dijkstra {// (vertex) -> indextemplate <class T, class Vertex>concept get_index = invocable<T, Vertex> && same_as<invoke_result_t<T, Vertex>, int>;// (vertex) -> is_goaltemplate <class T, class Vertex>concept is_goal = invocable<T, Vertex> && same_as<invoke_result_t<T, Vertex>, bool>;// (vertex, distance) -> voidtemplate <class T, class Vertex, class Weight>concept visit_adjacent_vertices =invocable<T, Vertex, Weight> && same_as<invoke_result_t<T, Vertex, Weight>, void>;template <class Vertex, class Weight, Weight Infinity, int MaxVertexIndex>requires(integral<Weight> || floating_point<Weight>)class dijkstra {private:using vw = pair<Vertex, Weight>;static constexpr int VERTEX_ARRAY_SIZE = MaxVertexIndex + 1;vector<vw> toVisit;bool visiting = false;public:array<bool, VERTEX_ARRAY_SIZE> visited;array<Weight, VERTEX_ARRAY_SIZE> distance;array<optional<Vertex>, VERTEX_ARRAY_SIZE> previous;dijkstra() {}template <get_index<Vertex> GetIndex, is_goal<Vertex> IsGoal,visit_adjacent_vertices<Vertex, Weight> VisitAdjacentVertices>void run(const vector<Vertex>& starts, GetIndex get_index, IsGoal is_goal,VisitAdjacentVertices visit_adjacent_vertices) {auto comp = [](vw& a, vw& b) {return a.second > b.second;};visited.fill(false);previous.fill(nullopt);distance.fill(Infinity);priority_queue<vw, vector<vw>, decltype(comp)> q(comp);for (auto& st : starts) {distance[get_index(st)] = Weight(0);q.emplace(st, Weight(0));}int loop = 0;while (!q.empty()) {if (++loop % 10 == 0)trace(loop, " ", timer::timer());auto [from, dist] = q.top();q.pop();int fromi = get_index(from);if (visited[fromi])continue;visited[fromi] = true;if (is_goal(from)) {return;}visiting = true;toVisit.clear();visit_adjacent_vertices(from, dist);visiting = false;for (vw& pair : toVisit) {Vertex to = pair.first;int toi = get_index(to);Weight new_dist = pair.second;if (new_dist < distance[toi]) {distance[toi] = new_dist;previous[toi] = from;q.emplace(to, new_dist);}}}}void visit(Vertex vertex, Weight total_distance) {assert(("not visiting now", visiting));toVisit.emplace_back(vertex, total_distance);}template <get_index<Vertex> GetIndex>vector<Vertex> restore_path(Vertex goal, GetIndex get_index) {assert(("goal not reached", visited[get_index(goal)]));vector<Vertex> res;Vertex v = goal;while (true) {res.push_back(v);if (!previous[get_index(v)])break;v = previous[get_index(v)].value();}reverse(res.begin(), res.end());return res;}};}; // namespace dijkstranamespace file {string pad4(int n) {return (n < 0 || n >= 1000 ? "" : n < 10 ? "000" : n < 100 ? "00" : "0") + tos(n);}string input_file_name(int seed) {return "in/" + pad4(seed) + ".txt";}string output_file_name(int seed) {return "out/" + pad4(seed) + ".txt";}string movie_file_name(int seed) {return "mov/" + pad4(seed) + ".smv";}bool write_text(string fileName, string text, bool append = false) {ofstream fout;fout.open(fileName, append ? ios::out | ios::app : ios::out);if (!fout)return false;fout << text;fout.close();return true;}pair<string, bool> read_text(string fileName) {ifstream fin;fin.open(fileName, ios::in);if (!fin)return make_pair("", false);string res;string line;while (getline(fin, line)) {res += line;res += "\n";}return make_pair(res, true);}void write_text_assert(string fileName, string text, bool append = false) {auto res = write_text(fileName, text, append);assert(res);}string read_text_assert(string fileName) {auto res = read_text(fileName);assert(res.second);return res.first;}} // namespace file} // namespace shrusing namespace shr::basic;using namespace shr::ds;using namespace shr::beam_search;using namespace shr::simulated_annealing;using namespace shr::dijkstra;using namespace shr::random;using namespace shr::timer;using namespace shr::tracer;using namespace shr::file;//// --- macros ---//#define rep(i, from, until) for (int i = (from); i < (until); i++)#define repr(i, from, until) for (int i = (until) -1; i >= (from); i--)#define rep0(i, until) rep(i, 0, until)#define rep0r(i, until) repr(i, 0, until)//// --- movie lib ---//class movie {private:bool is_open = false;string file_name;ofstream out;#ifdef ONLINE_JUDGEvoid write_instruction(const string& it, const vector<double>& argf, const vector<string>& args) {}#elsevoid write_instruction(const string& it, const vector<double>& argf, const vector<string>& args) {assert(("file name is not set", file_name != ""));if (!is_open) {is_open = true;out = ofstream(file_name, ios_base::out | ios_base::binary);out.write("smv", 3);}write_string(it);for (double f : argf) {write_float(f);}for (auto& s : args) {write_string(s);}if (it == "n") {out.flush(); // flush at the end of each frame}}void write_float(double a) {float f = (float) a;out.write((char*) &f, 4);}void write_string(const string& str) {out.write(str.c_str(), str.length() + 1);}#endifpublic:static constexpr int LEFT = 0;static constexpr int CENTER = 1;static constexpr int RIGHT = 2;movie() {}void set_file(string file) {assert(!is_open);file_name = file;}void close_file() {if (!is_open)return;is_open = false;out.close();}void fill(double rgb, double a = 1.0) {fill(rgb, rgb, rgb, a);}void fill(double r, double g, double b, double a = 1.0) {write_instruction("f", {r, g, b, a}, {});}void stroke(double rgb, double a = 1.0) {stroke(rgb, rgb, rgb, a);}void stroke(double r, double g, double b, double a = 1.0) {write_instruction("s", {r, g, b, a}, {});}void no_fill() {write_instruction("nf", {}, {});}void no_stroke() {write_instruction("ns", {}, {});}void comment(string text) {write_instruction("cm", {}, {text});}void tooltip(string text) {write_instruction("tt", {}, {text});}void no_tooltip() {write_instruction("nt", {}, {});}void stroke_weight(double weight) {write_instruction("sw", {weight}, {});}void text_size(double size) {write_instruction("ts", {size}, {});}void text_align(int align) {write_instruction("ta", {(double) align}, {});}void rect(double x, double y, double w, double h) {write_instruction("r", {x, y, w, h}, {});}void circle(double x, double y, double r) {write_instruction("c", {x, y, r}, {});}void ellipse(double x, double y, double rx, double ry) {write_instruction("e", {x, y, rx, ry}, {});}void line(double x1, double y1, double x2, double y2) {write_instruction("l", {x1, y1, x2, y2}, {});}void text(string str, double x, double y) {write_instruction("t", {x, y}, {str});}void transform(double e00, double e01, double e10, double e11) {write_instruction("tf", {e00, e01, e10, e11}, {});}void translate(double tx, double ty) {write_instruction("tr", {tx, ty}, {});}void rotate(double ang) {write_instruction("ro", {ang}, {});}void scale(double s) {scale(s, s);}void scale(double sx, double sy) {write_instruction("sc", {sx, sy}, {});}void push() {write_instruction("pu", {}, {});}void pop() {write_instruction("po", {}, {});}void end_frame() {write_instruction("n", {}, {});}void target(string name) {write_instruction("tg", {}, {name});}};movie mov;// --------------------------------------------------// main part// --------------------------------------------------bool isLocal = false;bool render = false;// define N and stuff hereconstexpr int N = 45;constexpr int N2 = N * 2;constexpr int M = 50;#define repn(i) rep0(i, N)#define repm(i) rep0(i, M)class Problem {private:public:array<array<ll, 2>, N> vs;void load(istream& in) {// read input hereint n;in >> n;assert(n == N);repn(i) {in >> vs[i][0] >> vs[i][1];}}};struct SolverResult {ll score = 0;};class Solver {public:int seed;rngen rng;SolverResult result;Problem p;Solver() : rng() {}void load(istream& in, int seed = -1) {p.load(in);mov.set_file(movie_file_name(seed));init();}void load(int seed) {this->seed = seed;istringstream in(read_text_assert(input_file_name(seed)));isLocal = true;load(in, seed);}void solve() {if (isLocal) {ostringstream out;solveMain(out);mov.close_file();write_text(output_file_name(seed), out.str());} else {solveMain(cout);}}private:void init() {}void solveMain(ostream& out) { // write answer to outconstexpr ll TARGET = (ll) (5e17);array<ll, N2> cs;repn(i) {cs[i << 1] = p.vs[i][0];cs[i << 1 | 1] = p.vs[i][1];}auto op = [&](int i, int j) {return make_pair(cs[i << 1] + cs[j << 1] >> 1, cs[i << 1 | 1] + cs[j << 1 | 1] >> 1);};auto getScore = [&](ll a, ll b) {return 20000000 - 100000 * log10(max(abs(a - TARGET), abs(b - TARGET)) + 1);};// vector<pii> ops;// repm(iter) {// double score = getScore(cs[0], cs[1]);// double bestScore = score;// int bestI = -1;// rep(i, 1, N) {// auto [a, b] = op(0, i);// double score = getScore(a, b);// if (update_max(score, bestScore)) {// bestI = i;// }// }// if (bestI == -1)// break;// auto [a, b] = op(0, bestI);// cs[0] = a;// cs[1] = b;// cs[bestI << 1 | 0] = a;// cs[bestI << 1 | 1] = b;// trace(bestI, " ", log10(max(abs(a - TARGET), abs(b - TARGET))), " ", bestScore, " ", iter);// }// out << len(ops) << endl;// for (auto [a, b] : ops) {// out << a + 1 << " " << b + 1 << endl;// }struct State {ll cs[N2];ll hist[M * 4];int ihist[M * 2];int turn = 0;};auto diff = [&](ll cs[N2], int i) {return max(abs(cs[i << 1] - TARGET), abs(cs[i << 1 | 1] - TARGET));};auto apply = [&](State& st, short move) {int i = move >> 8 & 0xff;int j = move & 0xff;ll ai = st.cs[i << 1];ll bi = st.cs[i << 1 | 1];ll aj = st.cs[j << 1];ll bj = st.cs[j << 1 | 1];ll a = ai + aj >> 1;ll b = bi + bj >> 1;st.hist[st.turn << 2 | 0] = ai;st.hist[st.turn << 2 | 1] = bi;st.hist[st.turn << 2 | 2] = aj;st.hist[st.turn << 2 | 3] = bj;st.ihist[st.turn << 1 | 0] = i;st.ihist[st.turn << 1 | 1] = j;st.cs[i << 1] = a;st.cs[i << 1 | 1] = b;st.cs[j << 1] = a;st.cs[j << 1 | 1] = b;st.turn++;};auto undo = [&](State& st) {st.turn--;int i = st.ihist[st.turn << 1 | 0];int j = st.ihist[st.turn << 1 | 1];ll ai = st.hist[st.turn << 2 | 0];ll bi = st.hist[st.turn << 2 | 1];ll aj = st.hist[st.turn << 2 | 2];ll bj = st.hist[st.turn << 2 | 3];ll a = st.cs[i << 1];ll b = st.cs[i << 1 | 1];st.cs[i << 1] = ai;st.cs[i << 1 | 1] = bi;st.cs[j << 1] = aj;st.cs[j << 1 | 1] = bj;};beam_search<State, ll, short, -1, ll, less<ll>, 24> bs;bs.max_turn = M;State st;repn(i) {st.cs[i << 1] = cs[i << 1];st.cs[i << 1 | 1] = cs[i << 1 | 1];}auto res = bs.run_tree(st,[&](State& st) {return max(abs(st.cs[0] - TARGET), abs(st.cs[1] - TARGET));},apply, undo,[&](State& st) {auto getScore = [&]() {ll res = diff(st.cs, 0);res += diff(st.cs, 1) >> 1;res += diff(st.cs, 2) >> 2;res += diff(st.cs, 3) >> 3;res += diff(st.cs, 4) >> 4;res += diff(st.cs, 5) >> 5;return res;};ll cscore = getScore();bs.add_candidate(0, cscore, 0);rep0(i, N - 1) {rep(j, i + 1, N) {apply(st, i << 8 | j);ll score = getScore();undo(st);bs.add_candidate(i << 8 | j, score, 0);}}},[&](int turn) {auto& cands = bs.candidates_to_filter();int bw = 300;auto better = [&](auto& a, auto& b) {return a.data < b.data;};trace(turn, " ", len(cands));static hash_imap<int> counts;counts.clear();if (len(cands) > bw) {ranges::sort(cands, better);erase_if(cands, [&](auto& a) {if (counts.access(a.parent)) {int num = counts.get();if (num > 10)return true;counts.set(num + 1);} else {counts.set(1);}return false;});if (len(cands) > bw) {nth_element(cands.begin(), cands.begin() + bw, cands.end(), better);cands.resize(bw);}}});erase_if(res, [&](auto move) {return move == 0;});trace(round(2e6 - 1e5 * log10(bs.best_score)) * 50);out << len(res) << endl;for (short move : res) {out << (move >> 8 & 0xff) + 1 << " " << (move & 0xff) + 1 << endl;// trace(move >> 8 & 0xff, " ", move & 0xff);}}};int main() {#if 0 || ONLINE_JUDGEisLocal = false;render = false;timer(true);Solver sol;sol.load(cin);sol.solve();#elif 0compareScores("cut", "nocut");// compareScores("new6", "new10");#elif 0// for local and remote testersdebug = false;render = false;int seed;cin >> seed;cin >> time_scale;timer(true);Solver sol;sol.load(seed);cout << sol.result.score << endl;#elif 1// single-threaded test, handy but slowtime_scale = 1.0;int num = 50;int from = 0;int stride = 1;int single = 0;debug = true;render = false;struct TestCase {int seed;int time;ll score;};vector<TestCase> cases;vector<int> seedList = {};if (seedList.empty()) {if (single == -1) {rep0(t, num) {seedList.push_back(from + t * stride);}} else {seedList.push_back(single);}}bool doTrace = debug;debug = true;for (int seed : seedList) {timer(true);trace("------------ SOLVING SEED ", seed, " ------------");debug = doTrace;Solver s;s.load(seed);s.solve();debug = true;int time = timer();trace("score: ", s.result.score, " (time ", time, " ms)\n");if (s.result.score != -1)cases.emplace_back(seed, time, s.result.score);}auto print = [&](const TestCase& c) {int seed = c.seed;string space = seed < 10 ? " " : seed < 100 ? " " : seed < 1000 ? " " : "";trace(" seed ", space, seed, ": ", c.score, " (time ", c.time, " ms)");};if (len(cases) > 1) {trace("------------ summary ------------");trace("sort by seed:");sort(cases.begin(), cases.end(), [&](auto a, auto b) {return a.seed < b.seed;});for (auto& c : cases)print(c);trace("sort by score:");sort(cases.begin(), cases.end(), [&](auto a, auto b) {return a.score > b.score;});for (auto& c : cases)print(c);ll scoreSum = 0;double logScoreSum = 0;for (auto& c : cases) {scoreSum += c.score;logScoreSum += log(c.score);}double invDenom = 1.0 / len(cases);trace("total score: ", scoreSum, ", mean: ", (ll) (scoreSum * invDenom * 100 + 0.5) / 100.0,", mean(log2): ", (ll) (logScoreSum * invDenom * 1000 + 0.5) / 1000.0);}#endif}