結果
| 問題 |
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;
}
ぴぃいいいい