結果
問題 |
No.5022 XOR Printer
|
ユーザー |
|
提出日時 | 2025-07-26 16:59:55 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,960 ms / 2,000 ms |
コード長 | 16,468 bytes |
コンパイル時間 | 5,373 ms |
コンパイル使用メモリ | 337,648 KB |
実行使用メモリ | 7,716 KB |
スコア | 5,212,104,942 |
最終ジャッジ日時 | 2025-07-26 17:06:08 |
合計ジャッジ時間 | 106,983 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
// (◕ᴗ◕✿) // #pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) #define srep(i, s, n) for (ll i = s; i < (n); ++i) #define len(x) ((int)(x).size()) #define all(x) (x).begin(), (x).end() using namespace std; template<typename T> using vc = vector<T>; template<typename T> using vv = vc<vc<T>>; using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>; using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>; using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>; using uint = unsigned int; using ull = unsigned long long; const ld pi = 3.141592653589793; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; // const ll mod = 1000000007; const ll mod = 998244353; #define debug(var) do{std::cout << #var << " : \n";view(var);}while(0) template<typename T> void view(T e){cout << e << endl;} template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;} template<typename T> void view(const vv<T>& vv){ for(const auto& v : vv){ view(v); } } // #define DEBUG #ifdef DEBUG constexpr bool DEBUGMODE = true; #else constexpr bool DEBUGMODE = false; #endif ofstream wrt; string outputfile = "output.txt", inputfile = "input.txt"; unsigned int randxor(){ static unsigned int x = 123456789, y = 362436069, z = 521288629, w = 88675123; unsigned int t; t = (x ^ (x << 11)); x = y; y = z; z = w; return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); } int randint(int a, int b) {return(a + randxor() % (b - a));} struct Timer { public: Timer(int limit){ start = chrono::high_resolution_clock::now(); goal = start + chrono::milliseconds(limit); } inline double rate(){ return (chrono::high_resolution_clock::now() - start).count() / (double)(goal - start).count(); } inline int get_time(){return (chrono::high_resolution_clock::now() - start).count() / 1e6;} private: chrono::high_resolution_clock::time_point start; chrono::high_resolution_clock::time_point goal; }; ll hilbertorder(int x, int y, ll maxn) { ll rx, ry, d = 0; for (ll s = maxn >> 1; s; s >>= 1) { rx = (x & s)>0, ry = (y & s)>0; d += s * s * ((rx * 3) ^ ry); if (ry) continue; if (rx) { x = maxn - 1 - x; y = maxn - 1 - y; } swap(x, y); } return d; } template<class T, int CAP> struct CapArr { int sz = 0; T arr[CAP]; CapArr() {} T& operator[](int i) { return arr[i]; } const T& operator[](int i) const { return arr[i]; } void push_back(const T& x){ arr[sz] = x; sz++; } void pop_back(){sz--;} void resize(int x){sz = x;} void clear(){sz = 0;} void shuffle(){ rep(i, sz - 1) swap(arr[i], arr[i + randint(0, sz - i)]); } template<int nCAP> void copy(const CapArr<T, nCAP> &A){ memcpy(arr, A.arr, sizeof(T) * A.sz); sz = A.sz; } void sort(){std::sort(arr, arr + sz);} void insert(int index, const T* mem, int size) { if (index == sz) { memcpy(arr + index, mem, sizeof(T) * size); sz += size; } else { memmove(arr + index + size, arr + index, sizeof(T) * (sz - index)); memcpy(arr + index, mem, sizeof(T) * size); sz += size; } } void multi_insert(int index, const T& val, int count) { // if (sz + count > CAP) return; if (index != sz) { memmove(arr + index + count, arr + index, sizeof(T) * (sz - index)); } std::fill(arr + index, arr + index + count, val); sz += count; } void remove(int start, int end) { int size = end - start; memmove(arr + start, arr + end, sizeof(T) * (sz - end)); sz -= size; } void RemoveInsert(int start, int end, const T* p, int size) { int newEnd = start + size; if (sz - end > 0 && newEnd != end) { memmove(arr + newEnd, arr + end, sizeof(T) * (sz - end)); } memcpy(arr + start, p, sizeof(T) * size); sz -= end - start; sz += size; } const T back(){return arr[sz - 1];} const int size()const{return sz;} }; //https://topcoder-tomerun.hatenablog.jp/entry/2021/06/12/134643 //改造済み... template<int length_MAX, int element_MAX> struct IndexSet { CapArr<int, length_MAX> que; int pos[element_MAX]; IndexSet() { rep(i, element_MAX) pos[i] = -1; } int operator[](int i)const{return que[i];} void add(int v) { if (pos[v] == -1){ pos[v] = que.sz; que.push_back(v); } } void remove(int v) { int p = pos[v]; int b = que.back(); que.arr[p] = b; que.pop_back(); pos[b] = p; pos[v] = -1; } bool contains(int v) const { return pos[v] != -1; } int size() const { return que.sz; } }; double log_table[70000]; //variable constexpr int TIME_LIMIT = 1940; constexpr int N = 10; constexpr int M = 100; constexpr int T = 1000; array<int, M> A; vi topbit[20]; array<int, M> eval; vi order; int mark[M]; namespace simulated_annealing { constexpr int transition_num = 5; int transition_count[transition_num]; int success_count[transition_num]; using Cost = int; struct Config { int time_limit; int temperature_type; double start_temp, goal_temp; int probability[transition_num]; }; struct State { Cost score; IndexSet<10, M> used; vi indexs; vvi path; State(){ score = -inf; } void operator=(const State &other) { score = other.score; indexs = other.indexs; } void init(){ used = IndexSet<10, M>(); indexs = {topbit[16][0], topbit[17][0], topbit[18][0], topbit[19][0], topbit[19][1], topbit[19][2]}; used.add(topbit[16][0]); used.add(topbit[17][0]); used.add(topbit[18][0]); used.add(topbit[19][0]); used.add(topbit[19][1]); used.add(topbit[19][2]); score = CalcScore(); } vvi buildans(){ int P = len(indexs); vi S(1, A[indexs[0]]); int nscore = 0, length = P + indexs[0] / N + indexs[0] % N; srep(i, 1, len(indexs)){ S.push_back(S.back() ^ A[indexs[i]]); length += abs(indexs[i - 1] / N - indexs[i] / N) + abs(indexs[i - 1] % N - indexs[i] % N); } vvi paths(P); rep(i, P) paths[i].push_back(indexs[i]); vi cmbs(1 << P, 0); rep(i, 1 << P){ rep(j, P) if (i >> j & 1) cmbs[i] ^= S[j]; } vi last(P, 0); rep(i, P) mark[indexs[i]] = i + 1; for (auto i : order){ int mask = (1 << mark[i]) - 1; int best = -1, bestcmb = -1; rep(cmb, 1 << P) if ((mask & cmb) == 0 && (A[i] ^ cmbs[cmb]) > best){ best = A[i] ^ cmbs[cmb]; bestcmb = cmb; } rep(j, P) if (bestcmb >> j & 1){ paths[j].push_back(i); length += abs(i / N - last[j] / N) + abs(i % N - last[j] % N) + 1; last[j] = i; } nscore += best; // cout << bestcmb << ' '; // if (i % N == N - 1) cout << endl; } rep(i, P){ mark[indexs[i]] = 0; length += last[i] / N + last[i] % N; } // 実際の長さはこれよ真に短くなるはず if (length > T) nscore = -inf; return paths; } Cost CalcScore(){ int P = len(indexs); vi S(1, A[indexs[0]]); int nscore = 0, length = P + indexs[0] / N + indexs[0] % N; srep(i, 1, len(indexs)){ S.push_back(S.back() ^ A[indexs[i]]); length += abs(indexs[i - 1] / N - indexs[i] / N) + abs(indexs[i - 1] % N - indexs[i] % N); } vi cmbs(1 << P, 0); rep(i, 1 << P){ rep(j, P) if (i >> j & 1) cmbs[i] ^= S[j]; } vi last(P, 0); rep(i, P) mark[indexs[i]] = i + 1; for (auto i : order){ int mask = (1 << mark[i]) - 1; int best = -1, bestcmb = -1; rep(cmb, 1 << P) if ((mask & cmb) == 0 && (A[i] ^ cmbs[cmb]) > best){ best = A[i] ^ cmbs[cmb]; bestcmb = cmb; } rep(j, P) if (bestcmb >> j & 1){ length += abs(i / N - last[j] / N) + abs(i % N - last[j] % N) + 1; last[j] = i; } nscore += best; // cout << bestcmb << ' '; // if (i % N == N - 1) cout << endl; } rep(i, P){ mark[indexs[i]] = 0; length += last[i] / N + last[i] % N; } // 実際の長さはこれよ真に短くなるはず if (length > T) nscore = -inf; return nscore; } void transition01(Cost &threshold){ transition_count[0]++; int id = randint(0, len(indexs)), tp = randint(15, 20); while (len(topbit[tp]) == 0) tp = randint(15, 20); int tpi = randint(0, len(topbit[tp])); if (used.contains(topbit[tp][tpi])) return; int last = indexs[id]; indexs[id] = topbit[tp][tpi]; auto new_score = CalcScore(); if (new_score >= threshold){ success_count[0]++; score = new_score; used.remove(last); used.add(indexs[id]); }else{ indexs[id] = last; } } void transition02(Cost &threshold){ // swap transition_count[1]++; int id = randint(0, len(indexs)), jd = randint(0, len(indexs)); while (id == jd){ jd = randint(0, len(indexs)); } swap(indexs[id], indexs[jd]); auto new_score = CalcScore(); if (new_score >= threshold){ success_count[1]++; score = new_score; }else{ swap(indexs[id], indexs[jd]); } } void transition03(Cost &threshold){ // push transition_count[2]++; int tp = 19; int tpi = randint(0, len(topbit[tp])); if (used.contains(topbit[tp][tpi])) return; indexs.push_back(topbit[tp][tpi]); auto new_score = CalcScore(); if (new_score >= threshold){ success_count[2]++; score = new_score; used.add(indexs.back()); }else{ indexs.pop_back(); } } void transition04(Cost &threshold){ // pop transition_count[3]++; int id = randint(0, len(indexs)); vi lstindex = indexs; indexs.erase(indexs.begin() + id); auto new_score = CalcScore(); if (new_score >= threshold){ success_count[3]++; score = new_score; used.remove(lstindex[id]); }else{ swap(indexs, lstindex); } } void transition05(Cost &threshold){ // kick transition_count[4]++; Cost p = score - 2e7; rep(i, 3) transition01(p); success_count[4]++; } }; State simulated_annealing(const Config& config, State state) { State best; Timer timer(config.time_limit); int roop = 0; double tmp = config.start_temp; double rate = 0; while (true){ roop++; int randomint = randint(0, 1000); Cost threshold = state.score + tmp * log_table[randint(0, 70000)]; if (randomint < config.probability[0]){ // transition 01 state.transition01(threshold); }else if (randomint < config.probability[1]){ state.transition02(threshold); }else if (randomint < config.probability[2]){ state.transition03(threshold); }else if (randomint < config.probability[3]){ state.transition04(threshold); }else{ state.transition05(threshold); } if (best.score < state.score){ // update best best = state; } if (roop % 1000 == 0){ // if (roop % 10000 == 0) cerr << state.score << " " << best.score << endl; rate = timer.rate(); if (config.temperature_type == 0){ tmp = config.start_temp + rate * (config.goal_temp - config.start_temp); }else{ tmp = config.start_temp * pow(config.goal_temp / config.start_temp, rate); } if (rate > 1.0){ break; } } } cerr << "roop : " << roop << endl; cerr << "score : " << best.score << endl; rep(i, transition_num) cerr << "transition" << i << " conversion rate : " << fixed << setprecision(4) << success_count[i] / (double)transition_count[i] * 100 << " % " << success_count[i] << " / " << transition_count[i] << endl; return best; }; }// namespace simulated_annealing struct Solver{ simulated_annealing::State ans; void input(){ if (DEBUGMODE){ ifstream in(inputfile); cin.rdbuf(in.rdbuf()); int a; cin >> a >> a; rep(i, M) cin >> A[i]; }else{ int a; cin >> a >> a; rep(i, M) cin >> A[i]; } } void init(){ double n = 1 / (double)(2 * 70000); for (int i = 0; i < 70000; i++) { log_table[i] = log(((double)i / 70000) + n); } rep(i, M) topbit[31 - __builtin_clz(A[i])].push_back(i); ll maxn = 1; while (maxn < N) maxn <<= 1; rep(i, N){ srep(j, 1, N) eval[i * N + j] = hilbertorder(i, j - 1, maxn) + 1; } int s = eval[(N - 1) * N + 1]; for (int i = N - 1; i >= 0; i--){ s++; eval[i * N] = s; } eval[0] = 0; order.resize(M); iota(all(order), 0); sort(all(order), [&](auto i, auto j){return eval[i] < eval[j];}); } void move(int s, int t){ if (DEBUGMODE){ while (s / N < t / N){ wrt << 'D' << endl; s += N; } while (s / N > t / N){ wrt << 'U' << endl; s -= N; } while (s % N < t % N){ wrt << 'R' << endl; s++; } while (s % N > t % N){ wrt << 'L' << endl; s--; } }else{ while (s / N < t / N){ cout << 'D' << endl; s += N; } while (s / N > t / N){ cout << 'U' << endl; s -= N; } while (s % N < t % N){ cout << 'R' << endl; s++; } while (s % N > t % N){ cout << 'L' << endl; s--; } } } void output(){ rep(p, len(ans.path)){ int frst = ans.path[p][0]; sort(all(ans.path[p]), [&](auto i, auto j){ return eval[i] < eval[j];}); int id = 0; rep(i, len(ans.path[p])) if (ans.path[p][i] == frst){id = i; break;} rotate(ans.path[p].begin(), ans.path[p].begin() + id, ans.path[p].end()); } int pos = 0; for (auto p : ans.path){ rep(i, len(p)){ move(pos, p[i]); pos = p[i]; if (DEBUGMODE){ if (i == 0) wrt << 'C' << endl; else wrt << 'W' << endl; }else{ if (i == 0) cout << 'C' << endl; else cout << 'W' << endl; } } } } void run(){ Timer timer(TIME_LIMIT); input(); init(); simulated_annealing::Config config = { TIME_LIMIT - timer.get_time(), 0, 15.0, 0.0, {850, 960, 975, 990, 1000} }; simulated_annealing::State state; state.init(); ans = simulated_annealing::simulated_annealing(config, state); ans.path = ans.buildans(); rep(i, len(ans.indexs)){ cerr << A[ans.indexs[i]] << ' ' << 31 - __builtin_clz(A[ans.indexs[i]]) << endl; } output(); } }; int main(){ wrt.open(outputfile, ios::out); ios_base::sync_with_stdio(false); cin.tie(nullptr); Solver solver; solver.run(); wrt.close(); return 0; }