結果
問題 |
No.5022 XOR Printer
|
ユーザー |
![]() |
提出日時 | 2025-07-28 19:39:33 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,804 ms / 2,000 ms |
コード長 | 14,285 bytes |
コンパイル時間 | 2,094 ms |
コンパイル使用メモリ | 203,256 KB |
実行使用メモリ | 7,716 KB |
スコア | 4,605,841,118 |
最終ジャッジ日時 | 2025-07-28 19:41:10 |
合計ジャッジ時間 | 96,507 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
#include <iostream> #include <vector> #include <algorithm> #include <cmath> #include <random> #include <chrono> #include <climits> #include <cassert> #include <cstring> using namespace std; // ===== グローバル変数と定数 ===== int N, T; vector<vector<int>> A; mt19937 rng; constexpr int MAX_ROUNDS = 6; constexpr double TIME_LIMIT = 1.8; constexpr double START_TEMP = 300000.0; constexpr double END_TEMP = 0.001; // ===== 最適化されたデータ構造 ===== // キャッシュ効率を考慮したアクション配列 struct alignas(16) FastAction { uint64_t copy_bits; // 各周回のコピーフラグをビットパック uint64_t write_bits; // 各周回の書き込みフラグをビットパック FastAction() : copy_bits(0), write_bits(0) {} inline bool getCopy(int round) const { return (copy_bits >> round) & 1; } inline bool getWrite(int round) const { return (write_bits >> round) & 1; } inline void setCopy(int round, bool value) { if (value) { copy_bits |= (1ULL << round); } else { copy_bits &= ~(1ULL << round); } } inline void setWrite(int round, bool value) { if (value) { write_bits |= (1ULL << round); } else { write_bits &= ~(1ULL << round); } } inline void flip(int round, bool is_copy) { if (is_copy) { copy_bits ^= (1ULL << round); } else { write_bits ^= (1ULL << round); } } }; // 最適化されたソリューション struct alignas(16) FastSolution { FastAction actions[100]; // 固定サイズ配列でキャッシュ効率向上 long long score; FastSolution() : score(0) {} // 高速コピー inline void copyFrom(const FastSolution& other) { memcpy(actions, other.actions, sizeof(actions)); score = other.score; } }; // ===== 最適化されたゲームシミュレーター ===== class OptimizedGameSimulator { private: alignas(16) int route_r[100]; // 行座標を事前計算 alignas(16) int route_c[100]; // 列座標を事前計算 alignas(16) int grid_flat[100]; // グリッドを1次元配列に平坦化 public: OptimizedGameSimulator() { // 蛇行ルートを事前計算して配列に格納 int idx = 0; for (int i = 0; i < N; i++) { if (i % 2 == 0) { for (int j = 0; j < N; j++) { route_r[idx] = i; route_c[idx] = j; idx++; } } else { for (int j = N - 1; j >= 0; j--) { route_r[idx] = i; route_c[idx] = j; idx++; } } } } // 最適化されたスコア計算 inline long long calculateScore(const FastSolution& sol) { // グリッドを1次元配列にコピー(キャッシュ効率向上) for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { grid_flat[i * N + j] = A[i][j]; } } int s = 0; int operations = 0; int currentR = 0, currentC = 0; // 複数周回の処理(最適化版) for (int round = 0; round < MAX_ROUNDS && operations < T; round++) { for (int i = 0; i < 100 && operations < T; i++) { int targetR = route_r[i]; int targetC = route_c[i]; // マンハッタン距離による高速移動計算 int move_ops = abs(currentR - targetR) + abs(currentC - targetC); operations += move_ops; currentR = targetR; currentC = targetC; if (operations >= T) break; int cell_idx = currentR * N + currentC; // コピー操作 if (sol.actions[i].getCopy(round) && operations < T) { operations++; s ^= grid_flat[cell_idx]; } // 書き込み操作 if (sol.actions[i].getWrite(round) && operations < T) { operations++; grid_flat[cell_idx] ^= s; } } } // 高速合計計算(ループアンローリング) return calculateOptimizedSum(); } private: // ループアンローリングによる高速合計計算 inline long long calculateOptimizedSum() { long long total = 0; // 4つずつまとめて処理(ループアンローリング) int i = 0; for (; i <= 96; i += 4) { total += grid_flat[i] + grid_flat[i+1] + grid_flat[i+2] + grid_flat[i+3]; } // 残りの要素を処理 for (; i < 100; i++) { total += grid_flat[i]; } return total; } }; // ===== 高速化された最適化器 ===== class TurboOptimizer { private: OptimizedGameSimulator simulator; // 高速乱数生成器(xorshift) uint64_t xorshift_state; inline uint64_t xorshift64() { xorshift_state ^= xorshift_state << 13; xorshift_state ^= xorshift_state >> 7; xorshift_state ^= xorshift_state << 17; return xorshift_state; } inline double fastRandom() { return (xorshift64() & 0x7FFFFFFF) * (1.0 / 2147483648.0); } inline int fastRandomInt(int max_val) { return xorshift64() % max_val; } public: TurboOptimizer() { xorshift_state = chrono::high_resolution_clock::now().time_since_epoch().count(); } // 高速初期解生成 FastSolution generateInitialSolution() { FastSolution sol; // 事前計算された確率テーブルを使用 static const double copy_probs[MAX_ROUNDS] = {0.55, 0.44, 0.35, 0.28, 0.22, 0.18}; static const double write_probs[MAX_ROUNDS] = {0.45, 0.36, 0.29, 0.23, 0.18, 0.15}; for (int i = 0; i < 100; i++) { // 境界効果の事前計算 int row = i / N; int col = i % N; double boundary_factor = (row == 0 || row == N-1 || col == 0 || col == N-1) ? 1.4 : 1.0; for (int round = 0; round < MAX_ROUNDS; round++) { double copy_threshold = copy_probs[round] * boundary_factor; double write_threshold = write_probs[round] * boundary_factor; sol.actions[i].setCopy(round, fastRandom() < copy_threshold); sol.actions[i].setWrite(round, fastRandom() < write_threshold); } } sol.score = simulator.calculateScore(sol); return sol; } // 超高速近傍生成 inline FastSolution generateNeighbor(const FastSolution& current) { FastSolution neighbor; neighbor.copyFrom(current); // 適応的変更数(ビット操作で高速化) int change_count = 1 + (fastRandomInt(100) < 25) + (fastRandomInt(100) < 10); for (int k = 0; k < change_count; k++) { int cell = fastRandomInt(100); int round = fastRandomInt(MAX_ROUNDS); bool is_copy = fastRandomInt(2) == 0; neighbor.actions[cell].flip(round, is_copy); } neighbor.score = simulator.calculateScore(neighbor); return neighbor; } // ターボ焼きなまし法 FastSolution optimize() { auto start_time = chrono::high_resolution_clock::now(); FastSolution current = generateInitialSolution(); FastSolution best = current; FastSolution global_best = current; int iter = 0; int accepted = 0; int improvements = 0; int restarts = 0; // 温度計算用の定数を事前計算 const double log_temp_ratio = log(END_TEMP / START_TEMP); // 高速exp近似用のテーブル static bool exp_table_initialized = false; static double exp_table[10000]; if (!exp_table_initialized) { for (int i = 0; i < 10000; i++) { exp_table[i] = exp(-i * 0.001); } exp_table_initialized = true; } while (true) { auto current_time = chrono::high_resolution_clock::now(); double elapsed = chrono::duration<double>(current_time - start_time).count(); if (elapsed >= TIME_LIMIT) break; double progress = elapsed / TIME_LIMIT; // 高速温度計算 double temp = START_TEMP * exp(log_temp_ratio * progress); FastSolution neighbor = generateNeighbor(current); double delta = neighbor.score - current.score; bool accept = false; if (delta > 0) { accept = true; improvements++; } else if (temp > END_TEMP) { // 高速exp近似(テーブル参照) double ratio = -delta / temp; if (ratio < 10.0) { int table_idx = (int)(ratio * 1000); if (table_idx < 10000) { accept = (fastRandom() < exp_table[table_idx]); } } } if (accept) { current.copyFrom(neighbor); accepted++; if (current.score > global_best.score) { global_best.copyFrom(current); } } // 適応的再スタート if (iter % 100000 == 0 && progress > 0.1 && progress < 0.8) { if (improvements < iter / 2000) { current = generateInitialSolution(); restarts++; } } // デバッグ出力の頻度を調整 if (iter % 25000 == 0) { double acceptance_rate = (double)accepted / max(1, iter); cerr << "Time: " << elapsed << "s, Temp: " << temp << ", Accept: " << acceptance_rate << ", Score: " << current.score << ", Best: " << global_best.score << ", Restarts: " << restarts << endl; } iter++; } cerr << "Final: " << iter << " iterations, " << improvements << " improvements, " << restarts << " restarts, Best score: " << global_best.score << endl; return global_best; } }; // ===== 高速操作列生成 ===== vector<char> generateFastOperations(const FastSolution& sol) { vector<char> operations; operations.reserve(T); // メモリ再確保を防ぐ int currentR = 0, currentC = 0; // 事前計算されたルート static const pair<int, int> route[100] = { {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9}, {1,9},{1,8},{1,7},{1,6},{1,5},{1,4},{1,3},{1,2},{1,1},{1,0}, {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9}, {3,9},{3,8},{3,7},{3,6},{3,5},{3,4},{3,3},{3,2},{3,1},{3,0}, {4,0},{4,1},{4,2},{4,3},{4,4},{4,5},{4,6},{4,7},{4,8},{4,9}, {5,9},{5,8},{5,7},{5,6},{5,5},{5,4},{5,3},{5,2},{5,1},{5,0}, {6,0},{6,1},{6,2},{6,3},{6,4},{6,5},{6,6},{6,7},{6,8},{6,9}, {7,9},{7,8},{7,7},{7,6},{7,5},{7,4},{7,3},{7,2},{7,1},{7,0}, {8,0},{8,1},{8,2},{8,3},{8,4},{8,5},{8,6},{8,7},{8,8},{8,9}, {9,9},{9,8},{9,7},{9,6},{9,5},{9,4},{9,3},{9,2},{9,1},{9,0} }; for (int round = 0; round < MAX_ROUNDS && operations.size() < T; round++) { for (int i = 0; i < 100 && operations.size() < T; i++) { int targetR = route[i].first; int targetC = route[i].second; // 高速移動操作生成 while ((currentR != targetR || currentC != targetC) && operations.size() < T) { if (currentR < targetR) { operations.push_back('D'); currentR++; } else if (currentR > targetR) { operations.push_back('U'); currentR--; } else if (currentC < targetC) { operations.push_back('R'); currentC++; } else { operations.push_back('L'); currentC--; } } if (operations.size() >= T) break; // アクション生成 if (sol.actions[i].getCopy(round) && operations.size() < T) { operations.push_back('C'); } if (sol.actions[i].getWrite(round) && operations.size() < T) { operations.push_back('W'); } } } return operations; } // ===== メイン処理 ===== void input() { cin >> N >> T; A.resize(N, vector<int>(N)); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { cin >> A[i][j]; } } } int main() { // 最適化バージョンの表示 cerr << "Portable Optimized Version - No SIMD" << endl; auto start_time = chrono::high_resolution_clock::now(); rng.seed(chrono::duration_cast<chrono::nanoseconds>(start_time.time_since_epoch()).count()); input(); cerr << "N=" << N << ", T=" << T << ", Grid size=" << N*N << endl; cerr << "Max rounds=" << MAX_ROUNDS << ", Time limit=" << TIME_LIMIT << "s" << endl; TurboOptimizer optimizer; FastSolution bestSolution = optimizer.optimize(); vector<char> operations = generateFastOperations(bestSolution); for (char op : operations) { cout << op << endl; } return 0; }