結果
| 問題 |
No.5022 XOR Printer
|
| コンテスト | |
| ユーザー |
tnktsyk
|
| 提出日時 | 2025-07-26 14:59:36 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 288 ms / 2,000 ms |
| コード長 | 7,784 bytes |
| コンパイル時間 | 2,623 ms |
| コンパイル使用メモリ | 221,708 KB |
| 実行使用メモリ | 7,716 KB |
| スコア | 4,648,420,920 |
| 最終ジャッジ日時 | 2025-07-26 14:59:55 |
| 合計ジャッジ時間 | 18,489 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge6 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| 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];
vector< vector<int> > idxs[B]; // store list of indices forming the vector (instead of bitset to stay flexible)
XorBasis(){ memset(v,0,sizeof(v)); }
void add(int x, const vector<int>& cells){
vector<int> c = cells;
for(int b=B-1;b>=0;--b){
if(((x>>b)&1)==0) continue;
if(v[b]==0){ v[b]=x; idxs[b]= {c}; return; }
x ^= v[b];
// xor index lists (symmetric difference)
vector<int> nc; nc.reserve(c.size()+idxs[b][0].size());
// because both lists are small (<=100) we can brute force
auto &v1 = c; auto &v2 = idxs[b][0];
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
size_t i=0,j=0;
while(i<v1.size()||j<v2.size()){
if(j==v2.size() || (i<v1.size() && v1[i]<v2[j])){ nc.push_back(v1[i]); ++i; }
else if(i==v1.size() || v2[j]<v1[i]){ nc.push_back(v2[j]); ++j; }
else{ // equal -> cancel
++i; ++j;
}
}
c.swap(nc);
}
}
// build target -> {built_value, indices}
pair<int, vector<int>> build(int target) const{
int t=target, made=0; vector<int> sel;
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];
// xor lists
vector<int> nc; nc.reserve(sel.size() + idxs[b][0].size());
auto v1 = sel; auto v2 = idxs[b][0];
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
size_t i=0,j=0;
while(i<v1.size()||j<v2.size()){
if(j==v2.size() || (i<v1.size() && v1[i]<v2[j])){ nc.push_back(v1[i]); ++i; }
else if(i==v1.size() || v2[j]<v1[i]){ nc.push_back(v2[j]); ++j; }
else{ ++i; ++j; }
}
sel.swap(nc);
}
return {made, sel};
}
};
inline long long score_single(const vector<int>& A, int s){
long long res=0; for(int x:A){ int y=x^s; res += (y>x?y:x);} return res; }
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;
vector<vector<int>> A2(N, vector<int>(N));
for(int i=0;i<N;i++)for(int j=0;j<N;j++) cin>>A2[i][j];
const int NN=N*N;
vector<int> Aflat(NN); for(int i=0;i<N;i++)for(int j=0;j<N;j++) Aflat[i*N+j]=A2[i][j];
// Build basis on original board
XorBasis B1;
for(int i=0;i<N;i++)for(int j=0;j<N;j++){
int idx=i*N+j; B1.add(A2[i][j], vector<int>{idx});
}
// 1) best single s (exact exhaustive)
int s1=0; long long best1=-1;
for(int s=0;s<(1<<20);++s){
long long sc=score_single(Aflat,s);
if(sc>best1){best1=sc;s1=s;} }
auto [s1_real, cset1] = B1.build(s1);
if(s1_real!=s1){ long long sc=score_single(Aflat,s1_real); if(sc>=best1){best1=sc;s1=s1_real;} }
if(s1_real!=s1){ auto tmp=B1.build(s1); cset1=tmp.second; }
// base per cell after stage1 best of {A, A^s1}
vector<int> baseVal(NN); long long baseSum=0;
for(int i=0;i<NN;i++){ int a=Aflat[i]; int b=a^s1; baseVal[i]=(b>a?b:a); baseSum+=baseVal[i]; }
// 2) Find s2 by exhaustive to maximize 4-way value
int s2=-1; long long gainBest=0;
for(int s=0;s<(1<<20);++s){
long long sum=0;
for(int i=0;i<NN;i++){
int a=Aflat[i];
int v0=baseVal[i];
int v1=a^s; // only stage2
int v2=(a^s1)^s; // both stages
int m=v0; if(v1>m)m=v1; if(v2>m)m=v2; sum+=m;
}
long long g=sum-baseSum; if(g>gainBest){gainBest=g; s2=s;}
}
bool use2 = (gainBest>0);
vector<unsigned char> choice(NN,0); // 0 none,1 stage1W,2 stage2W,3 both
if(!use2){
for(int i=0;i<NN;i++){ int a=Aflat[i]; choice[i]= ((a^s1)>a?1:0); }
}else{
// map s2 to achievable after stage1 W changes, so we need to rebuild basis later
// First decide ideal masks with target s2
for(int i=0;i<NN;i++){
int a=Aflat[i]; int v0=a; int v1=a^s1; int v2=a^s2; int v3=a^(s1^s2);
int best=v0; unsigned char m=0;
if(v1>best){best=v1;m=1;} if(v2>best){best=v2;m=2;} if(v3>best){best=v3;m=3;}
choice[i]=m;
}
}
// === Simulate stage1 W to know board for second basis ===
vector<int> Aafter = Aflat;
if(use2){
for(int i=0;i<NN;i++) if(choice[i]&1) Aafter[i]^=s1; // stage1 writes
}
// Build basis on modified board to realize delta = s1->s2
vector<int> csetDelta; int deltaReal=0; int deltaTarget=0;
if(use2){
deltaTarget = s1 ^ s2;
XorBasis B2; for(int i=0;i<N;i++)for(int j=0;j<N;j++){ int idx=i*N+j; B2.add(Aafter[idx], vector<int>{idx}); }
auto [dReal, csetD] = B2.build(deltaTarget);
deltaReal=dReal; csetDelta=csetD;
int s2_real = s1 ^ deltaReal;
if(s2_real!=s2){
// recompute gain and masks with s2_real to ensure non-decreasing
long long sum=0; vector<unsigned char> newChoice(NN);
for(int i=0;i<NN;i++){
int a=Aflat[i]; int v0=a; int v1=a^s1; int v2=a^s2_real; int v3=a^(s1^s2_real);
int best=v0; unsigned char m=0;
if(v1>best){best=v1;m=1;} if(v2>best){best=v2;m=2;} if(v3>best){best=v3;m=3;}
newChoice[i]=m; sum+=best;
}
if(sum<=baseSum){ use2=false; choice.assign(NN,0); for(int i=0;i<NN;i++){int a=Aflat[i]; choice[i]=((a^s1)>a?1:0);} }
else{ choice.swap(newChoice); gainBest=sum-baseSum; s2=s2_real; }
}
}
// ===== Build operation sequence =====
vector<char> ops; int r=0,c=0;
vector<pair<int,int>> snake; snake.reserve(NN);
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);
}
auto output_C = [&](const vector<int>& cells){
// we'll simply visit along snake and C when needed
vector<char> mark(NN,0); for(int id:cells) mark[id]=1;
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(mark[id]) ops.push_back('C');
if(k+1<snake.size()){
auto [nr,nc]=snake[k+1]; move_to(r,c,nr,nc,ops);
}
}
}
};
// Phase A: make s1
output_C(cset1);
// Phase B: stage1 writes (reverse snake)
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 id=rr*N+cc; if(choice[id]&1) ops.push_back('W');
}
}
if(use2){
// Phase C: move delta C's
output_C(csetDelta);
// Phase D: stage2 writes
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 id=rr*N+cc; if(choice[id]&2) ops.push_back('W');
}
}
}
if((int)ops.size()>T) ops.resize(T);
for(char ch:ops) cout<<ch<<'\n';
return 0;
}
tnktsyk