POJ 1222
0x11 1x12 1x13 0x14
1x21 0x22 0x23 1x24
0x31 0x32 1x33 0x34
1x41 0x42 0x43 1x44
-> simply
[ 0 0 0 0] [0 1 1 0] -> b[1][1] = x11^ x12^ x13 ^ a[1][1] -> b[1][1] ^ a[1][1] = x11^ x12^ x13 -> a[1][1] = x11 ^ x12 ^ x13
[ 0 0 0 0] [1 0 0 1] -> b[1][2] = x11^ x12^ x13 ^ x22 ^ a[1][2] -> b[1][2] ^ a[1][2] = x11^ x12^ x13 ^ x22 -> a[1][2] = x11 ^ x12 ^ x13 ^ x22
[ 0 0 0 0] [0 0 1 0] so a[2][2] = x21 ^ x22 ^ x32 ^ x21 ^ x23
[ 0 0 0 0] [1 0 0 1]
then -> a[num] = x[1]*Map[num][1] ^ … ^ x[16]*Map[num][16]
a(16*1) = Map(16*16)(* ^)x(16*1)
Gauss-> Map(16*17) -> cal x(16*1)
in this problem Gauss(equ = 30, var = 30) Map(30,31) -> x(30,1)
确定好每个a[i][j] 正好是 结果矩阵,再添30个方程,和关系矩阵即可
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
//0x11 1x12 1x13 0x14
//1x21 0x22 0x23 1x24
//0x31 0x32 1x33 0x34
//1x41 0x42 0x43 1x44
//-> simply
//[ 0 0 0 0] [0 1 1 0] -> b[1][1] = x11^ x12^ x13 ^ a[1][1] -> b[1][1] ^ a[1][1] = x11^ x12^ x13 -> a[1][1] = x11 ^ x12 ^ x13
//[ 0 0 0 0] [1 0 0 1] -> b[1][2] = x11^ x12^ x13 ^ x22 ^ a[1][2] -> b[1][2] ^ a[1][2] = x11^ x12^ x13 ^ x22 -> a[1][2] = x11 ^ x12 ^ x13 ^ x22
//[ 0 0 0 0] [0 0 1 0] so a[2][2] = x21 ^ x22 ^ x32 ^ x21 ^ x23
//[ 0 0 0 0] [1 0 0 1]
//then -> a[num] = x[1]*Map[num][1] ^ ... ^ x[16]*Map[num][16]
//a(16*1) = Map(16*16)(* ^)x(16*1)
//Gauss-> Map(16*17) -> cal x(16*1)
// in this problem Gauss(equ = 30, var = 30) Map(30,31) -> x(30,1)
const int maxn = 50;
int a[maxn][maxn]; // zeng guang
int x[maxn] ; // ans_x
int free_x[maxn] ;
// 8 6 (6,2) (2,0)
inline int gcd(int a , int b) {
return b == 0 ? a : gcd(b,a%b) ;
/*int t ;
while(b){
t = b ;
b = a%b ;
a = t ;
}
return a;*/
}
inline int lcm(int a ,int b){
return a/gcd(a,b)*b;
}
inline int Abs(int a ){
return a > 0 ? a : -a;
}
void debug(int equ , int var){
for(int i = 0 ; i < equ ; ++i){
for(int j = 0 ;j <= var ; ++j){
cout << a[i][j] << " " ;
}
cout << endl;
}
}
int Gauss(int equ , int var) {
int max_r ;
for(int i = 0 ; i <= var ; ++i){
free_x[i] = false ;
x[i] = 0 ;
}
//cout << equ << " " << var << endl;
int row , col ;
for(row = 0 ,col = 0 ; row < equ && col < var ; ++row , ++col) {
max_r = row ;
for(int i = row+1 ; i < equ ; ++i){ // find the max element in this col
if(Abs(a[max_r][col]) < Abs(a[i][col])) max_r = i;
}
if(max_r != row){
for(int j = col ; j <= var ; ++j){ // change
swap(a[max_r][j],a[row][j]) ;
}
}
if(!a[row][col]) { // 0
row--;
continue ;
}
//debug(3,3) ;
for(int i = row+1 ; i < equ ; ++i){
if(a[i][col]){// sub a[i][col] -> 0
/* int tmp = lcm(abs(a[i][col]),abs(a[row][col])) ;
int up = tmp/(abs(a[row][col])) ;
int down = tmp/(abs(a[i][col])) ;
//cout << tmp << " " << up << " " << down << endl;
if(a[i][col]*a[row][col]<0) up = -up ;
for(int j = col ; j <= var; ++j){
a[i][j] = a[i][j]*down - a[row][j]*up ;
} */
for(int j = 0 ; j <= var ; ++j){
a[i][j] ^= a[row][j] ;
}
}
}
//system("pause") ;
}
// col == var , [row,equ) == all of 0000...a
for(int i = row ; i < equ ; ++i){
if(a[i][col] != 0) {
return -1 ; // no solve
}
}
/* if(row < var){ //[row , equ -1 ] -> (000.000) have free_x ,at least var - row . cal the x[]
int free_index ;
for(int i = row-1; i >= 0; --i){
int free_num = 0 ;
for(int j = i; j < var; ++j){
if(a[i][j]&&(!free_x[j])) {
free_num++ ;
free_index = j ;
}
}
if(free_num > 1) continue ; // free_x > 1 , can't solve
// solve the free__index;
int tmp = a[i][var] ;
for(int j = i ; j < var ; ++j){
if(a[i][j] && j != free_index) {
tmp -= a[i][j]*x[j] ;
}
}
x[free_index] = tmp/a[i][free_index] ; // solve the x of a[i][free_index] ;
free_x[free_index] = true ; // solvable
}
return var - row ;
} */
// only have one ans and must be the ans
for(int i = equ-1 ; i >= 0 ; --i){
bool tmp = a[i][var] ;
/*for(int j = i+1 ; j < var ; ++j){
if(a[i][j])
tmp -= a[i][j]*x[j] ;
}*/
// if(tmp%a[i][i] != 0 ) double ans
for(int j = i+1 ; j < var ; ++j){
if(a[i][j])
tmp ^= x[j] ;
}
x[i] = tmp ;
//x[i] = tmp/a[i][i] ;
}
return 0;
}
void init(int var){
for(int row=0; row<var; ++row){
for(int col=0; col<var; ++col){
a[row][col] = false;
/*row-1>=0&&col-1>=0 ? a[row-1][col-1] = true : a[row-1][col-1] = false;
row-1>=0 ? a[row-1][col] = true : a[row-1][col] = false;
col+1<var ? a[row][col+1] = true : a[row][col+1] = false;
col+1<var&&row+1<var ? a[row+1][col+1] = true : a[row+1][col+1] = false;*/
}
}
for(int i = 0 ;i < 5 ; ++i){
for(int j = 0 ;j < 6 ; ++j){
int tmp = i*6+j ;
if(i==0&&j==0) a[tmp][tmp+1] = a[tmp][tmp+6] = a[tmp][tmp] = true ;
else if(i==0&&j==5) a[tmp][tmp] = a[tmp][tmp-1] = a[tmp][tmp+6] = true ;
else if(i==4&&j==0) a[tmp][tmp] = a[tmp][tmp-6] = a[tmp][tmp+1] = true ;
else if(i==4&&j==5) a[tmp][tmp] = a[tmp][tmp-6] = a[tmp][tmp-1] = true ;
else if(j==0) a[tmp][tmp-6] = a[tmp][tmp] = a[tmp][tmp+6] = a[tmp][tmp+1] = true ;
else if(j==5) a[tmp][tmp-6] = a[tmp][tmp] = a[tmp][tmp+6] = a[tmp][tmp-1] = true ;
else if(i==0) a[tmp][tmp+1] = a[tmp][tmp] = a[tmp][tmp+6] = a[tmp][tmp-1] = true ;
else if(i==4) a[tmp][tmp+1] = a[tmp][tmp] = a[tmp][tmp-6] = a[tmp][tmp-1] = true ;
else a[tmp][tmp] = a[tmp][tmp+6] = a[tmp][tmp-6] = a[tmp][tmp+1] = a[tmp][tmp-1] = true ;
}
}
// debug(var,var) ;
// system("pause") ;
return ;
}
int main(){
int t ,cas = 1;
cin >> t ;
while(t--){
int var = 5*6 ;
init(var) ;
for(int i=0; i<5*6; ++i){
cin >> a[i][var] ;
}
// debug(30,30) ;
int flag = Gauss(var,var) ;
if(!flag){
char ch[] = "PUZZLE #";
printf("%s%d\n",ch,cas++) ;
for(int i = 0 , cnt = 1 ;i < 30 ; ++i,cnt++){
cnt%6 ? printf("%d ",x[i]) : printf("%d\n",x[i]) ;
}
}
}
return 0;
}