結果
問題 |
No.5022 XOR Printer
|
ユーザー |
![]() |
提出日時 | 2025-07-26 14:32:57 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,922 ms / 2,000 ms |
コード長 | 6,926 bytes |
コンパイル時間 | 2,763 ms |
コンパイル使用メモリ | 214,080 KB |
実行使用メモリ | 7,720 KB |
スコア | 4,009,322,051 |
最終ジャッジ日時 | 2025-07-26 14:34:39 |
合計ジャッジ時間 | 101,717 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; // ===== XOR Basis (20-bit) ===== struct XorBasis { static const int B = 20; int v[B]; bitset<128> used[B]; XorBasis(){ memset(v,0,sizeof(v)); } void add(int x, const bitset<128>& bs){ bitset<128> c = bs; for(int b=B-1;b>=0;--b){ if(((x>>b)&1)==0) continue; if(v[b]==0){ v[b]=x; used[b]=c; return; } x ^= v[b]; c ^= used[b]; } } pair<int, bitset<128>> build(int target) const { int t = target, made = 0; bitset<128> sel; sel.reset(); for(int b=B-1;b>=0;--b){ if(((t>>b)&1)==0) continue; if(v[b]==0) continue; t ^= v[b]; made ^= v[b]; sel ^= used[b]; } return {made, sel}; } }; // score for a given s static inline long long eval_score(const vector<int>& flatA, int s){ long long sum = 0; for(int x: flatA){ int y = x ^ s; sum += (y > x ? y : x); } return sum; } // move helper static inline void move_to(int &r,int &c,int tr,int tc, vector<char>& ops){ while(r<tr){ ops.push_back('D'); ++r; } while(r>tr){ ops.push_back('U'); --r; } while(c<tc){ ops.push_back('R'); ++c; } while(c>tc){ ops.push_back('L'); --c; } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N,T; if(!(cin>>N>>T)) return 0; // N=10, T=1000 vector<vector<int>> A(N, vector<int>(N)); for(int i=0;i<N;i++) for(int j=0;j<N;j++) cin>>A[i][j]; // flatten vector<int> flatA(N*N); for(int i=0;i<N;i++) for(int j=0;j<N;j++) flatA[i*N+j] = A[i][j]; // --- initial candidates --- int s0 = 0; // your greedy for(int i=0;i<N;i++) for(int j=0;j<N;j++) if(s0 < (s0 ^ A[i][j])) s0 ^= A[i][j]; int s1_target = 0; // per-bit gain for(int b=0;b<20;b++){ int cnt0=0,cnt1=0; for(int x: flatA){ if((x>>b)&1) cnt1++; else cnt0++; } if(cnt0 > cnt1) s1_target |= (1<<b); } // basis XorBasis basis; for(int i=0;i<N;i++) for(int j=0;j<N;j++){ bitset<128> bs; bs.reset(); bs.set(i*N + j); basis.add(A[i][j], bs); } auto [s0_real, cells0] = basis.build(s0); auto [s1_real, cells1] = basis.build(s1_target); long long sc0 = eval_score(flatA, s0_real); long long sc1 = eval_score(flatA, s1_real); int S = s0_real; bitset<128> needC = cells0; long long bestScore = sc0; if(sc1 > sc0){ S = s1_real; needC = cells1; bestScore = sc1; } // ===== Deterministic hill climbing (1,2,3 XOR) ===== auto single_step = [&](int &Sref, long long &cur){ long long base = cur; int bestIdx = -1; long long bestGain = 0; for(int i=0;i<N*N;i++){ int ns = Sref ^ flatA[i]; long long sc = eval_score(flatA, ns); if(sc - base > bestGain){ bestGain = sc - base; bestIdx = i; } } if(bestGain>0){ Sref ^= flatA[bestIdx]; cur += bestGain; return true; } return false; }; auto pair_step = [&](int &Sref, long long &cur){ long long base = cur; long long bestGain = 0; int bi=-1,bj=-1; for(int i=0;i<N*N;i++){ for(int j=i+1;j<N*N;j++){ int ns = Sref ^ flatA[i] ^ flatA[j]; long long sc = eval_score(flatA, ns); if(sc - base > bestGain){ bestGain=sc-base; bi=i; bj=j; } } } if(bestGain>0){ Sref ^= flatA[bi]; Sref ^= flatA[bj]; cur += bestGain; return true; } return false; }; auto triple_step = [&](int &Sref, long long &cur){ long long base = cur; long long bestGain = 0; int bi=-1,bj=-1,bk=-1; for(int i=0;i<N*N;i++){ for(int j=i+1;j<N*N;j++){ for(int k=j+1;k<N*N;k++){ int ns = Sref ^ flatA[i] ^ flatA[j] ^ flatA[k]; long long sc = eval_score(flatA, ns); if(sc - base > bestGain){ bestGain=sc-base; bi=i; bj=j; bk=k; } } } } if(bestGain>0){ Sref ^= flatA[bi]; Sref ^= flatA[bj]; Sref ^= flatA[bk]; cur += bestGain; return true; } return false; }; // loop until no improvement while(true){ if(single_step(S, bestScore)) continue; if(pair_step(S, bestScore)) continue; if(triple_step(S, bestScore)) continue; break; } // ===== Optional random search within time budget ===== auto start = chrono::steady_clock::now(); mt19937 rng(1234567); auto time_ok = [&](){ return chrono::duration<double>(chrono::steady_clock::now()-start).count() < 1.85; // adjust margin }; vector<int> idxs(N*N); iota(idxs.begin(), idxs.end(), 0); while(time_ok()){ int k = 1 + (rng()%4); // 1..4 elements shuffle(idxs.begin(), idxs.end(), rng); int ns = S; for(int i=0;i<k;i++) ns ^= flatA[idxs[i]]; long long sc = eval_score(flatA, ns); if(sc > bestScore){ S = ns; bestScore = sc; // after a random improvement, run deterministic singles again while(true){ if(single_step(S, bestScore)) continue; if(pair_step(S, bestScore)) continue; if(triple_step(S, bestScore)) continue; break; } } } // rebuild for final S auto [S_real, cells_final] = basis.build(S); if(S_real != S){ long long sc_real = eval_score(flatA, S_real); if(sc_real >= bestScore){ S = S_real; bestScore = sc_real; needC = cells_final; } else needC = cells_final; // keep S; slight mismatch unlikely but allow } else { needC = cells_final; } // ===== Construct operations ===== vector<char> ops; int r=0,c=0; // snake path vector<pair<int,int>> snake; snake.reserve(N*N); for(int i=0;i<N;i++){ if(i%2==0) for(int j=0;j<N;j++) snake.emplace_back(i,j); else for(int j=N-1;j>=0;j--) snake.emplace_back(i,j); } if(!snake.empty()){ move_to(r,c, snake[0].first, snake[0].second, ops); for(size_t k=0;k<snake.size();k++){ int rr = snake[k].first, cc = snake[k].second; int id = rr*N + cc; if(needC.test(id)) ops.push_back('C'); if(k+1<snake.size()){ auto [nr,nc] = snake[k+1]; move_to(r,c,nr,nc,ops); } } } // reverse snake for W if(!snake.empty()){ for(size_t k=0;k<snake.size();k++){ auto [rr,cc] = snake[snake.size()-1-k]; if(k>0) move_to(r,c, rr, cc, ops); int x = A[rr][cc]; if( (x ^ S) > x ) ops.push_back('W'); } } if((int)ops.size() > T) ops.resize(T); // unlikely, but safeguard for(char ch: ops) cout << ch << '\n'; return 0; }