// Alternative solution for problem A // Author: Lech Duraj // Use Gauss elimination to determine flipping parity. Still very fast. #include #include #include #include #include #include #include #define REP(i,n) for(int i=0;i<(n);++i) #define SIZE(c) ((int)((c).size())) #define FOR(i,a,b) for (int i=(a); i<(b); ++i) #define FOREACH(i,x) for (__typeof((x).begin()) i=(x).begin(); i!=(x).end(); ++i) #define FORD(i,a,b) for (int i=((int)(a))-1; i>=(b); --i) using namespace std; namespace Gauss { const int N = 10001; const int M = 10001; typedef unsigned long long ULL; ULL A[N][(M+63)/64]; bool B[N]; bool X[M]; int gauss(int n, int m) { int dim=0, P[m]; REP(i,m) P[i]=i; REP(i,n) { int r=i,c=i; FOR(j,i,n) FOR(k,i,m) { if (A[j][k/64]&(1ULL<<(k&63))) { r=j; c=k; goto found; } } break; found: dim = i+1; if (r != i) { REP(j,(m+63)/64) std::swap(A[i][j], A[r][j]); std::swap(B[i], B[r]); } if (c != i) { REP(j,n) { if ((((A[j][i/64]&(1ULL<<(i&63)))>>(i&63))) != ((A[j][c/64]&(1ULL<<(c&63)))>>(c&63))) { A[j][i/64] ^= (1ULL<<(i&63)); A[j][c/64] ^= (1ULL<<(c&63)); } } std::swap(P[i], P[c]); } FOR(j,i+1,n) { if (A[j][i/64]&(1ULL<<(i&63))) { REP(k,(m+63)/64) A[j][k] ^= A[i][k]; if (B[i]) B[j] ^= 1; } } } FOR(i,dim,n) if (B[i]!=0) return -1; FOR(i,dim,m) X[i] = 0; FORD(i,dim,0) { FOR(j,i+1,m) { B[i] ^= (X[j] && (A[i][j/64]&(1ULL<<(j&63)))); } X[i] = B[i]; } REP(i,m) REP(j,m) if (P[j]==i) { std::swap(P[j], P[i]); std::swap(X[j], X[i]); break; } return m-dim; } }; struct permutation { vector m; // (0,1,2,3) -> (0 1) vector row; // (2 3) vector col; permutation(vector v) { map M; for(int j=0; j<4; j++) M[v[j]] = 0; int i = 0; for(map::iterator t=M.begin(); t!=M.end(); t++) M[t->first] = i++; m.resize(4); for(int j=0; j<4; j++) m[j] = M[v[j]]; row.resize(2,0); col.resize(2,0); }; }; bool operator<(permutation p, permutation q) { return p.m moves; vector > A; vector > B; int w,h; vector make_quad(vector > &P, int i, int j) { vector quad; quad.push_back(P[i][j]); quad.push_back(P[i][w-1-j]); quad.push_back(P[h-1-i][j]); quad.push_back(P[h-1-i][w-1-j]); return quad; } void preprocessing() { queue Q; vector v; for(int j=0; j<4; j++) v.push_back(j); permutation id(v); moves[id] = ""; Q.push(id); while(!Q.empty()) { permutation p = Q.front(); Q.pop(); for(int i=0; i<4; i++) { permutation r = p; string rmov = moves[p]; switch(i) { case 0: swap(r.m[0],r.m[1]); r.row[0] = !r.row[0]; rmov += '0'; break; case 1: swap(r.m[2],r.m[3]); r.row[1] = !r.row[1]; rmov += '1'; break; case 2: swap(r.m[0],r.m[2]); r.col[0] = !r.col[0]; rmov += '2'; break; case 3: swap(r.m[1],r.m[3]); r.col[1] = !r.col[1]; rmov += '3'; break; } if (moves.find(r)==moves.end()) { moves[r] = rmov; Q.push(r); } } } }; typedef pair PP; vector output; void flip_row(int r, bool trueflip = false) { output.push_back(PP('R',r+1)); if (trueflip) for(int j=0 ;j> TT; while(TT--) { cin >> w >> h; A.resize(h); B.resize(h); for(int i=0; i> A[i][j]; B[i][j] = i*w+j+1; } } bool ok = true; if (h%2==1) { if (A[h/2][0]!=B[h/2][0]) flip_row(h/2, true); for(int j=0; j quad = make_quad(A,i,j); vector quadsorted = make_quad(B,i,j); vector quad2 = quad; sort(quad2.begin(),quad2.end()); ok &= (quad2==quadsorted); permutation p(quad); bool odd = (moves.find(p)==moves.end()); for(int v = 0; v<(var+63)/64; v++) Gauss::A[eq][v] = 0; Gauss::B[eq] = odd; int v1 = i; int v2 = h/2+j; Gauss::A[eq][v1/64] += 1ULL<<(v1%64); Gauss::A[eq][v2/64] += 1ULL<<(v2%64); eq++; } ok &= Gauss::gauss(eq,var)!=-1; for(int i=0; i=0; k--) switch(s[k]) { case '0' : flip_row(i); break; case '1' : flip_row(h-1-i); break; case '2' : flip_col(j); break; case '3' : flip_col(w-1-j); break; } } cout << (ok ? "POSSIBLE " : "IMPOSSIBLE"); if (ok) { cout << output.size(); for(int i=0; i