結果
| 問題 | No.5022 XOR Printer |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-07-26 19:09:02 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,974 ms / 2,000 ms |
| コード長 | 9,129 bytes |
| コンパイル時間 | 2,669 ms |
| コンパイル使用メモリ | 225,584 KB |
| 実行使用メモリ | 7,716 KB |
| スコア | 5,156,979,105 |
| 最終ジャッジ日時 | 2025-07-26 19:10:49 |
| 合計ジャッジ時間 | 106,223 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge6 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
ソースコード
/*
No.5022 XOR Printer
20bit分考えるらしい
上bitから変更していくと良いのかも?
乱択をたくさんやる
*/
#include<bits/stdc++.h>
using namespace std;
using ll = long long;//int型は使わない
using vecl = vector<ll>;
using graph = vector<vector<ll>>;
using pll = pair<ll , ll>;
const ll inf = (1LL<<61); //約2e18
const ll MOD = 998244353;
const vecl dx={1,0,-1,0};
const vecl dy={0,1,0,-1};
#define rep(i,a,b) for(ll i=(ll)a; i<(ll)b; i++)
#define rrep(i,a,b) for(ll i=(ll)b-1; i>=(ll)a; i--)
#define all(vec1) (vec1).begin(), (vec1).end()
#define debug(var) cerr << #var << " : " << var << endl;
template<typename... Args>
void eerr(Args&&... args){
((std::cerr << args << ' '), ...) << '\n';
}
template<typename T>
std::istream& operator>>(std::istream& is, std::vector<T>& v) {
v.clear();
std::string line;
std::getline(is >> std::ws, line); // 1行丸ごと読み込み
std::stringstream ss(line);
T x;
while (ss >> x) {
v.push_back(x);
}
return is;
}
//fastio
struct FastIO {
FastIO() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
}
} fastio;
//modulo
template<typename T>
T ovr(T a,T b){
T ret=a%b;
if(ret<0)ret+=b;
return ret;
}
namespace Rand
{
unsigned long long XSseed = 12345678987654321;
unsigned long long rand64u()
{
XSseed ^= XSseed << 13;
XSseed ^= XSseed >> 7;
XSseed ^= XSseed << 17;
return XSseed ;
}
double randf()
{
return double(rand64u())/ULLONG_MAX ;
}
ll randint(ll MIN,ll MAX)
{
if(MAX-MIN<=0)
{
cerr << "Rand:randint: warn : MIN > MAX" << endl ;
return MIN ;
}
return MIN+ll(rand64u()%(unsigned long long)(MAX-MIN));
}
//scoreは大きいほどよいときに使える関数
ll rand_pick(vecl Vs , double temp)
{
if(Vs.size() == 0)return -1 ;
//選ぶ
ll ret = 0 ;
rep(i,0,Vs.size())
{
if(Vs[i] > Vs[ret])
{
ret = i ;
}
}
if(exp(Vs[ret] / temp) > randf())
{
return ret ;
}else
{
return -1 ;
}
}
}
double get_time()
{
return chrono::duration<double>(chrono::steady_clock::now().time_since_epoch()).count();
}
struct Time_Keeper
{
double time_limit;
ll counter = 0;
ll freq = 1 ;
double begin_time = get_time();
vector<double> time_log ; //timeを記録しておく
double start_time;
Time_Keeper(double tm) : time_limit(0){
time_limit = tm ;
}
//焼きなましを始める時(ただし初期解生成後)
void start(){
start_time = get_time() ;
}
//t(0<=t<=1でスケーリングしたもの)を返す
double get_t(){
double pre_time ;//計測はfreq回に1回することにする
if(counter % freq == 0){
pre_time = get_time() ;
time_log.push_back(pre_time) ;
}
else{
if(time_log.size() < 2){
pre_time = get_time() ;
}
else{
//線形補間する
double tmp = time_log[time_log.size() - 1] - time_log[time_log.size() - 2];
pre_time = time_log.back() + tmp * (counter % freq) / freq;
}
}
counter ++ ;
return (pre_time - start_time) / (time_limit - (start_time - begin_time)) ;
}
};
struct solution {
pair<ll, string> best_sol = {-inf, ""}; // 最良の解法
string current_sol = ""; // 現在構築中の解法
ll current_score = -inf;
// 新しい解法を開始
void new_sol() {
current_sol = "";
}
// 現在の解法に手順を追加
void print(const string & x) {
current_sol += x;
}
void set_score(ll x) {
current_score = x;
}
// 現在の解法をbest_solと比較し、更新する
void update_sol() {
if (current_score > best_sol.first) {
best_sol = {current_score , current_sol};
}
}
// 最良の解法を出力
void print_best_sol() {
cerr << "best_score : " << best_sol.first << endl;
rep(i,0,best_sol.second.size()){
cout << best_sol.second[i] << endl;
}
}
};
solution SOL;
///variable
ll n,t;
ll s = 0;
graph save_a , a;
ll nx = 0 , ny = 0 ;
void ReadInput(){
cin >> n >> t;
save_a.resize(n) ;
rep(i,0,n){rep(j,0,n){ll x;cin >> x;save_a[i].push_back(x);}}
}
void load(){
a = save_a ;
t = 1000 ;
s = 0;
nx = ny = 0;
}
ll g_now_x(ll gr_id){
return gr_id / n;
}
ll g_now_y(ll gr_id){
if(gr_id / n % 2 == 0){
return gr_id % n;
}else{
return n - 1 - gr_id % n;
}
}
bool inc(){
t -- ;
return (t == 0);
}
void debug_binary(ll x, const string& label = "") {
if (!label.empty()) cerr << label << " : ";
for (ll i = 20 - 1; i >= 0; --i) {
cerr << ((x >> i) & 1);
}
cerr << " (" << x << ")\n";
}
bool pri_move(ll ax , ll ay , ll bx , ll by){
if(ax < bx){
for(ll _ = bx - ax ; _-- ; ){
SOL.print("D") ;if(inc())return true;
}
}else{
for(ll _ = ax - bx ; _-- ; ){
SOL.print("U") ;if(inc())return true;
}
}
if(ay < by){
for(ll _ = by - ay ; _-- ; ){
SOL.print("R") ;if(inc())return true;
}
}else{
for(ll _ = ay - by ; _-- ; ){
SOL.print("L") ;if(inc())return true;
}
}
return false;
}
vector<pll> get_best_combination(ll g) {
ll n = a.size();
vector<pll> result = {};
ll best_score = inf;
if((s>>g)&1){
best_score = s;
}
// 1個だけ
rep(i1, 0, n) rep(j1, 0, n) {
ll bitsum = a[i1][j1] ^ s;
if (((bitsum >> g) & 1) == 1) {
if (bitsum < best_score) {
best_score = bitsum;
result = { {i1, j1} };
}
}
}
// 2個
rep(i1, 0, n) rep(j1, 0, n)
rep(i2, 0, n) rep(j2, 0, n) {
ll bitsum = a[i1][j1] ^ a[i2][j2] ^ s;
if (((bitsum >> g) & 1) == 1) {
if (bitsum < best_score) {
best_score = bitsum;
result = { {i1, j1}, {i2, j2} };
}
}
}
if(best_score == inf)return {{-1,-1}} ;
return result;
}
unordered_set<ll> skipgrid ;
bool bit(ll g){
//sのg bit目を1にする
vector<pll> vb = get_best_combination(g) ;
if(!vb.empty() && vb[0].first==-1)return false;//不可能
if(vb.size()>0)for(pll x : vb){
if(pri_move(nx , ny , x.first , x.second))return true;
SOL.print("C");if(inc())return true;
nx = x.first , ny = x.second ;
s^=a[x.first][x.second];
}
//debug_binary(s);
rep(i,0,n*n){
if(skipgrid.find(i) != skipgrid.end())continue;
if(pri_move(nx , ny , g_now_x(i) , g_now_y(i)))return true;
nx = g_now_x(i) , ny = g_now_y(i) ;
if((a[nx][ny]^s) > (a[nx][ny])){
SOL.print("W");if(inc())return true;
a[nx][ny] ^= s ;
}
}
return false;
}
int solve()
{
skipgrid = {} ;
ll times = rand() % 10 + 1;
rep(i,0,times)skipgrid.insert(Rand::randint(0 , n * n )) ;
SOL.new_sol() ;
rrep(i,1,20){
if(bit(i)){
break;
}
double base = std::max(1.0, (double)times + 1);
bool pd = Rand::randf() < (base - skipgrid.size()) / base ;
if (skipgrid.size() > 1 && pd) {
ll pos = *skipgrid.begin();
skipgrid.erase(skipgrid.begin());
ll kx = g_now_x(pos);
ll ky = g_now_y(pos);
// 最良の (bi, bj) を探す:a[bi][bj] ^ a[kx][ky] ^ s を最大化
ll best_val = s ^ a[kx][ky];
pll best_pos = {-1, -1};
rep(i, 0, n) rep(j, 0, n) {
if(kx == i && ky == j)continue;
ll val = a[i][j] ^ a[kx][ky] ^ s;
if (val > best_val) {
best_val = val;
best_pos = {i, j};
}
}
if (best_pos.first != -1) {
ll bi = best_pos.first;
ll bj = best_pos.second;
if (pri_move(nx, ny, bi, bj)) break;
nx = bi, ny = bj;
SOL.print("C");
if (inc()) break;
s ^= a[bi][bj]; // 変化させる
}
// 最後に (kx, ky) に行って 'C'
if (pri_move(nx, ny, kx, ky)) break;
nx = kx, ny = ky;
SOL.print("W");
if (inc()) break;
a[kx][ky] ^= s;
}
}
ll scr = 0;
rep(i,0,n)rep(j,0,n)scr+=a[i][j] ;
debug(scr);
SOL.set_score (scr);
SOL.update_sol();
cerr << t << endl;
return 0;
}
int main()
{
Time_Keeper tk(1.97) ;
tk.start();
ReadInput();
while(tk.get_t()<1)load(),solve();
SOL.print_best_sol() ;
}