結果
| 問題 | No.5022 XOR Printer |
| コンテスト | |
| ユーザー |
tabae326
|
| 提出日時 | 2025-07-26 16:39:08 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,804 ms / 2,000 ms |
| コード長 | 10,841 bytes |
| コンパイル時間 | 1,499 ms |
| コンパイル使用メモリ | 120,064 KB |
| 実行使用メモリ | 7,716 KB |
| スコア | 4,678,896,294 |
| 最終ジャッジ日時 | 2025-07-26 16:40:45 |
| 合計ジャッジ時間 | 95,187 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
ソースコード
#include <iostream>
#include <bitset>
#ifndef __ANNEALER_HPP__
#define __ANNEALER_HPP__
#ifndef __RYUKA_HPP__
#define __RYUKA_HPP__
#include <random>
using namespace std;
struct RandGenerator {
random_device seed_gen;
mt19937 engine;
mt19937_64 engine64;
static const int pshift = 1000000000;
RandGenerator() : engine(seed_gen()), engine64(seed_gen()) {}
int rand(int mod) { return engine() % mod; }
long long randll(long long mod) { return engine64() % mod; }
bool pjudge(double p) {
int p_int;
if (p > 1)
p_int = pshift;
else
p_int = p * pshift;
return rand(pshift) < p_int;
}
} ryuka;
#endif
#ifndef __TOKI_HPP__
#define __TOKI_HPP__
#include <sys/time.h>
#include <cstddef>
struct Timer {
double global_start;
double gettime() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec * 1e-6;
}
void init() { global_start = gettime(); }
double elapsed() { return gettime() - global_start; }
} toki;
#endif
extern Timer toki;
extern RandGenerator ryuka;
template <class STATE>
struct IterationControl {
long long iteration_counter;
long long swap_counter;
double average_time;
double start_time;
bool liner_cooling;
bool save_best_answer;
bool use_rollback;
bool maximize;
int gettime_interval;
IterationControl()
: iteration_counter(0),
swap_counter(0),
liner_cooling(false),
save_best_answer(true),
use_rollback(false),
maximize(true),
gettime_interval(1) {}
STATE climb(double time_limit, STATE initial_state);
STATE anneal(double time_limit, double temp_start, double temp_end,
STATE initial_state);
};
template <class STATE>
STATE IterationControl<STATE>::climb(double time_limit, STATE initial_state) {
start_time = toki.gettime();
average_time = 0;
STATE best_state = initial_state;
double time_stamp = start_time;
cerr << "Start climbing...\n";
while (time_stamp - start_time + average_time < time_limit) {
if (use_rollback) {
long long best_score = best_state.score;
best_state.nextState();
long long delta = best_state.score - best_score;
if (!maximize) {
delta = -delta;
}
if (delta > 0) {
swap_counter++;
} else {
best_state.rollback();
best_state.score = best_score;
}
} else {
STATE current_state = STATE::generateState(best_state);
long long delta = current_state.score - best_state.score;
if (!maximize) {
delta = -delta;
}
if (delta > 0) {
swap(best_state, current_state);
swap_counter++;
}
}
iteration_counter++;
if (iteration_counter % gettime_interval == 0) {
time_stamp = toki.gettime();
average_time = (time_stamp - start_time) / iteration_counter;
}
}
cerr << "Iterated " << iteration_counter << " times and swapped "
<< swap_counter << " times.\n";
return best_state;
}
template <class STATE>
STATE IterationControl<STATE>::anneal(double time_limit, double temp_start,
double temp_end, STATE initial_state) {
start_time = toki.gettime();
average_time = 0;
STATE current_state = initial_state;
STATE answer_state = initial_state;
double elapsed_time = 0;
const double inv_time_limit = 1.0 / time_limit;
cerr << "Start annealing...\n";
while (elapsed_time + average_time < time_limit) {
double temp_current;
if (liner_cooling) {
const double normalized_time = elapsed_time * inv_time_limit;
temp_current =
temp_start + (temp_end - temp_start) * normalized_time;
} else {
const double normalized_time = elapsed_time * inv_time_limit;
temp_current = pow(temp_start, 1.0 - normalized_time) *
pow(temp_end, normalized_time);
}
if (use_rollback) {
long long prev_score = current_state.score;
current_state.nextState();
long long delta = current_state.score - prev_score;
long long delta_ans = current_state.score - answer_state.score;
if (!maximize) {
delta = -delta;
delta_ans = -delta_ans;
}
if (save_best_answer && delta_ans > 0) {
answer_state = current_state;
}
if (delta > 0 || ryuka.pjudge(exp(1.0 * delta / temp_current))) {
swap_counter++;
} else {
current_state.rollback();
current_state.score = prev_score;
}
} else {
STATE new_state = STATE::generateState(current_state);
long long delta = new_state.score - current_state.score;
long long delta_ans = new_state.score - answer_state.score;
if (!maximize) {
delta = -delta;
delta_ans = -delta_ans;
}
if (save_best_answer && delta_ans > 0) {
answer_state = new_state;
}
if (delta > 0 || ryuka.pjudge(exp(1.0 * delta / temp_current))) {
swap(new_state, current_state);
swap_counter++;
}
}
iteration_counter++;
if (iteration_counter % gettime_interval == 0) {
elapsed_time = toki.gettime() - start_time;
average_time = elapsed_time / iteration_counter;
}
}
cerr << "Iterated " << iteration_counter << " times and swapped "
<< swap_counter << " times.\n";
return save_best_answer ? answer_state : current_state;
}
#endif
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
namespace common {
constexpr int n = 10;
constexpr int t = 1000;
int a[n][n];
void read();
void copy_a(int src[n][n], int dst[n][n]) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
dst[i][j] = src[i][j];
}
}
}
bool is_in_field(int i, int j) {
return i >= 0 && i < n && j >= 0 && j < n;
}
}; // namespace common
void common::read() {
int _n, _t;
cin >> _n >> _t;
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
}
#include <algorithm>
#include <cassert>
#include <numeric>
using namespace std;
using namespace common;
extern RandGenerator ryuka;
struct Operation {
char type;
pair<int, int> dir() const {
if(type == 'U') return {-1, 0};
if(type == 'D') return {1, 0};
if(type == 'L') return {0, -1};
if(type == 'R') return {0, 1};
assert(false && "Invalid operation type");
}
Operation(char t) : type(t) {}
Operation() = default;
};
struct State {
static constexpr long long inf = 1LL << 60;
static constexpr int num_c = 6;
long long score;
int a[n][n];
vector<pair<int,int>> c_pos;
vector<Operation> ops;
State() : score(-inf) { ; };
long long calc_score();
void apply(char, int&, int&, int&);
pair<int, int> move_to(int, int, int, int);
void fill_ops();
void print();
void rollback();
void nextState();
static State initState();
static State generateState(const State& input_state);
};
long long State::calc_score() {
score = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
score += this->a[i][j];
}
}
return score;
}
void State::print() {
for(const Operation& op: ops) {
cout << op.type << endl;
}
}
void State::apply(char type, int& i, int& j, int& s) {
if(type == 'U') {
i--;
} else if(type == 'D') {
i++;
} else if(type == 'L') {
j--;
} else if(type == 'R') {
j++;
} else if(type == 'C') {
s ^= this->a[i][j];
} else if(type == 'W') {
this->a[i][j] ^= s;
} else {
cerr << "Invalid operation type: " << type << endl;
assert(false);
}
ops.push_back(Operation(type));
}
pair<int, int> State::move_to(int si, int sj, int di, int dj) {
if(si == di && sj == dj) return {di, dj};
for(int i = si; i < di; i++) ops.push_back(Operation('D'));
for(int i = si; i > di; i--) ops.push_back(Operation('U'));
for(int j = sj; j < dj; j++) ops.push_back(Operation('R'));
for(int j = sj; j > dj; j--) ops.push_back(Operation('L'));
return {di, dj};
}
void State::fill_ops() {
int i = 0, j = 0, s = 0;
ops.clear();
copy_a(common::a, this->a);
for(auto [ni, nj]: c_pos) {
tie(i, j) = move_to(i, j, ni, nj);
apply('C', i, j, s);
tie(i, j) = move_to(i, j, 0, 0);
while(true) {
if((s ^ this->a[i][j]) > this->a[i][j]) apply('W', i, j, s);
if(i == n-1 && j == 0) break;
if(i % 2 == 0) {
if(j != n-1) apply('R', i, j, s);
else apply('D', i, j, s);
} else {
if(j != 0) apply('L', i, j, s);
else apply('D', i, j, s);
}
}
}
while(ops.size() > t) {
ops.pop_back();
}
}
State State::initState() {
State res;
for(int i = 0; i < num_c; i++) {
int x = ryuka.rand(n);
int y = ryuka.rand(n);
res.c_pos.emplace_back(x, y);
}
res.fill_ops();
res.calc_score();
return res;
}
State State::generateState(const State& input_state) {
State res = input_state;
if(ryuka.pjudge(0.5)) {
int i = ryuka.rand(num_c);
int j = ryuka.rand(num_c);
swap(res.c_pos[i], res.c_pos[j]);
} else {
int i = ryuka.rand(n);
int j = ryuka.rand(n);
int p = ryuka.rand(num_c);
res.c_pos[p] = {i, j};
}
res.fill_ops();
res.calc_score();
return res;
}
void State::nextState() {
}
void State::rollback() {
}
using namespace std;
using namespace common;
extern Timer toki;
int main() {
toki.init();
read();
IterationControl<State> sera;
//State stat = State::initState();
State stat = sera.anneal(1.8, 1e6, 1e-2, State::initState());
stat.print();
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
cerr << bitset<20>(stat.a[i][j]) << " ";
}
cerr << endl;
}
cerr << "my score = " << stat.score << endl;
cerr << "elapsed time = " << toki.elapsed() << endl;
}
tabae326