#include using namespace std; using ll = long long; /**************************************************** * "Try a lot, keep only improvements" framework * - N=10, T=1000, Ai < 2^20 固定前提。 * - 現在盤面boardと保持中sを持ち、いろんなヒューリスティックで候補sを作成。 * - 各候補ごとに実際の基底でdiffを構成→利得計算→ops/time内なら即採用。 * - 非劣化保証: gain<=0 なら採用しない。 * * Heuristics order (ループで繰り返し): * 1) 全体単一s 全探索 (最初の1回だけ) * 2) ブロックサイズ {5,4,3,2} 全探索 (全ブロック) * 3) ビットトグル利得最大 (1bitずつ) * 4) ランダムs候補 (RND_SAMPLES 回) * 5) ランダム小ブロック (RND_BLOCKS 回、サイズ2〜4) * これらを時間/手数が切れるまで回す。 * * ルーティング: 必要セルのみを貪欲巡回。 ****************************************************/ // ===== XOR Basis (20-bit) ===== struct XorBasis { static const int B = 20; int v[B]; vector mask[B]; XorBasis(){ memset(v,0,sizeof(v)); } void add(int x, const vector& cells){ vector c = cells; for(int b=B-1;b>=0;--b){ if(((x>>b)&1)==0) continue; if(!v[b]){ v[b]=x; mask[b]=c; return; } x ^= v[b]; vector a = mask[b], res; res.reserve(c.size()+a.size()); sort(c.begin(),c.end()); sort(a.begin(),a.end()); size_t i=0,j=0; while(i> build(int target) const{ int t=target, made=0; vector sel; for(int b=B-1;b>=0;--b){ if(((t>>b)&1)==0) continue; if(!v[b]) continue; t ^= v[b]; made ^= v[b]; vector a = mask[b], res; res.reserve(sel.size()+a.size()); sort(sel.begin(),sel.end()); sort(a.begin(),a.end()); size_t i=0,j=0; while(i& A, int s){ ll sum=0; for(int x:A){ int y=x^s; sum += (y>x?y:x); } return sum; } static void greedy_visit(int N,int &r,int &c,const vector& ids,vector& ops,char ch){ if(ids.empty()) return; vector used(ids.size(),0); for(size_t done=0; donerr){ ops.push_back('U'); --r; } while(ccc){ ops.push_back('L'); --c; } ops.push_back(ch); } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N,T; if(!(cin>>N>>T)) return 0; // N=10, T=1000 const int BITS=20, NN=100; vector> A(N,vector(N)); for(int i=0;i>A[i][j]; vector board(NN); for(int i=0;i ops; ops.reserve(5000); int r=0,c=0; int curS=0; mt19937 rng(114514); auto start = chrono::steady_clock::now(); const double TL = 1.90; auto time_ok=[&](){return chrono::duration(chrono::steady_clock::now()-start).count() all) auto try_apply = [&](int targetS, const vector& idsRestrict, bool strict_restrict)->bool{ if(!time_ok()) return false; ll base = total_sum(); // Build basis on current board XorBasis B; for(int i=0;i wCells; wCells.reserve(NN); ll after=0; if(idsRestrict.empty()){ for(int id=0; ida){ wCells.push_back(id); after+=b; } else after+=a; } }else{ vector mark(NN,0); for(int id:idsRestrict) mark[id]=1; for(int id=0; ida){ wCells.push_back(id); after+=b; } else after+=a; }else{ // outside block: keep as is after+=a; if(!strict_restrict) { // allow outside also if profitable (optional) if(b>a){ wCells.push_back(id); after-=a; after+=b; } } } } } ll gain = after - base; if(gain<=0) return false; // simulate ops vector tmp; tmp.reserve(needC.size()*6 + wCells.size()*6 + 10); int tr=r, tc=c; greedy_visit(N,tr,tc,needC,tmp,'C'); greedy_visit(N,tr,tc,wCells,tmp,'W'); if((int)ops.size() + (int)tmp.size() > T) return false; // commit ops.insert(ops.end(), tmp.begin(), tmp.end()); r=tr; c=tc; curS=newS; for(int id:wCells) board[id]^=curS; return true; }; // ---- 0) global best single s (once) ---- { ll base = total_sum(); int bestS=0; ll bestG=0; for(int s=0;s<(1<x?y:x);} ll g=tot-base; if(g>bestG){bestG=g; bestS=s;} } if(bestG>0) try_apply(bestS, {}, true); } // heuristic loop const int RND_SAMPLES = 2000; const int RND_BLOCKS = 800; vector blockSizes = {5,4,3,2}; bool improved=true; while(improved && time_ok() && (int)ops.size() <= T-200){ improved=false; // 1) block sizes deterministic scan for(int sz: blockSizes){ if(!time_ok() || (int)ops.size()>T-200) break; for(int rs=0; rs ids; ids.reserve(sz*sz); for(int i=rs;ia?b:a);} ll g=tot-blkBase; if(g>bg){bg=g; bs=s;} } if(bg<=0) continue; if(try_apply(bs, ids, true)) improved=true; } } } if(!time_ok() || (int)ops.size()>T-200) break; // 2) bit-greedy loop (one pass). Repeat outer while for more. for(int loop=0; loop<20 && time_ok() && (int)ops.size()<=T-200; ++loop){ ll base=total_sum(); // build basis once XorBasis B; for(int i=0;i bestNeedC, bestW; for(int b=BITS-1;b>=0;b--){ int diff = 1< wCells; for(int id=0; ida){ g+= (bval-a); wCells.push_back(id);} } if(g>gainBest || (g==gainBest && b>bestBit)){ gainBest=g; bestBit=b; bestNewS=newS; bestNeedC=needC; bestW=wCells; } } if(gainBest<=0) break; vector tmp; tmp.reserve(bestNeedC.size()*6 + bestW.size()*6 + 10); int tr=r, tc=c; greedy_visit(N,tr,tc,bestNeedC,tmp,'C'); greedy_visit(N,tr,tc,bestW,tmp,'W'); if((int)ops.size()+ (int)tmp.size() > T) break; ops.insert(ops.end(), tmp.begin(), tmp.end()); r=tr; c=tc; curS=bestNewS; for(int id:bestW) board[id]^=curS; improved=true; } if(!time_ok() || (int)ops.size()>T-200) break; // 3) random s full-board for(int k=0;kT-200) break; // 4) random small blocks with random s subset (cheap approx) for(int k=0;k ids; for(int i=rs;iT) ops.resize(T); for(char ch:ops) cout<