Problem:
博士の光電管

博士 : ピーター君。やったよ。

ピーター : またですか。今度はどんなくだらない発明ですか。

博士 : あの幻の素粒子アキシオンの検出器を発明したんじゃ。

ピーター : アキシオンといえば、欧州合同原子核研究機構 (CERN) をはじめとする研究者たちが血眼で追っかけているという、あれですよね。本当ですかぁ?

博士 : 本当だってばよ。細かい説明は省くが、非常に強力な磁場を内蔵する特殊な光電管が光ることによって、通過するアキシオンを検出する。

ピーター : 他 に先んじて検出すれば、小柴先生のニュートリノ検出に匹敵するノーベル賞級の研究ですよ。
これで役立たずの研究ばかりしている「ダメ研究室」などという汚名も返上できますね。

博士 : そうだとも。小柴先生の「スーパーカミオカンデ」にあやかって、この装置を、(悪口言ったら)「タダジャオカンデ」と命名した。

ピーター : ちょっと苦しいって言うか、卑屈って言うか・・・。

博士 : それはいいとして、この装置ちょっとした癖があるんじゃよ。
アキシオン粒子がある光電管を通過すると、感度の関係でその光電管と隣接する上下左右の光電管が反応する。

図1

図2

★

●

●

●

●

●

●

●

★

●

●

●

●

●

●

●

●

●

●

●

●

●

★

●

●

 

 

   →   

 

 

○

○

●

○

●

○

●

○

○

○

●

●

●

○

●

●

●

○

●

●

●

○

○

○

●

●

○

○

●

○

○

★

★

○

☆

●

●

○

●

●

○

●

●

○

●

●

○

○

○

●

 

 

   →   

 

 

●

●

●

●

●

●

●

●

○

●

●

○

●

●

○

○

●

●

○

●

●

○

○

○

●

ピーター : つまり、図1の左側★印の光電管を粒子が通過した場合、
右側のように点灯すると言うことですね。
(図は 5 × 5 の例。黒は消灯・白は点灯状態。以下同じ。)

博士 : また反応とは、光電管の状態が反転する。つまり消えている光電管は光り、
光っている光電管は消える。

ピーター : つまり、図2の左側の★印や☆印を粒子が通過した場合、右側のような状態になると。

博士 : これを正方形になんと 100 個 (10 × 10) 配置して待ち受けるわけだ。

ピーター : これだけの大発明、ノーベル賞選考委員会も「ホッチャオカンデ」なんて。

博士 : おぉピーター君、君も我が研究室の作風になじんできたようだね。いい感じだ。
では、早速実験を始めよう。まずはこの装置、現在ランダムに光電管が点いているので、
実験が始められるように全部消えた状態にリセットしてくれたまえ。
なあに、どの光電管にアキシオン粒子を当てれば全部消えるか考えればいいだけじゃよ。
簡単だろう?

ピーター : 考えるのはいいんですが博士。当てるためには、
幻のアキシオン粒子を発生させて打ち込める装置がないといけないんじゃないですか。

博士 : ・・・。

博士とピータ (同時に)コリャアカンデ!だははは・・・・。
ー:

ということで、本日も和気あいあいと暮れてゆく博士の研究室ですが、例によって話は全く進みそうもありません。しょうがないので、ピーター君に代わってプログラムを作成してあげてください。
プログラムは次のようなものになります。

A. 装置の光電管の状態を 10 × 10 の配列として入力します。0は消灯中、1は点灯中を表します。
0 と 1 以外のデータは含まれません。

B. 入力した装置の状態をすべて消灯にするために、アキシオン粒子を通過させる位置を計算して出力します。これは、入力と同じ 10 × 10の配列で光電管の位置を表します。「0 は通過させない」、「1 は通過させる」ことを表します。すべてを消灯する方法は必ず 1 通りだけ存在するものとします。

Input

複数のデータセットが与えられます。１行目にデータセットの数 n (n ≤ 20) が与えられます。各データセットは以下の形式で与えられます。

a1,1 a1,2 ... a1,10
a2,1 a2,2 ... a2,10
:
a10,1 a10,2 ... a10,10

ai,j は装置の i 行目 j 列目の光電管の状態を示す整数 (0 または 1) を表します。

Output

各データセットについて、粒子を通過させる位置を以下の形式で出力してください。

b1,1 b1,2 ... b1,10
b2,1 b2,2 ... b2,10
:
b10,1 b10,2 ... b10,10

bi,j は装置の i 行目 j 列目の光電管に粒子を通過させるかいなかを示す整数 (0 または 1) を表します。

Sample Input

1
0 1 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0 1 0

Output for the Sample Input

0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0

Solution in JAVA (judge verdict: Accepted)



import java.util.*;

import java.lang.*;

import java.math.*;



public class Main {

	Scanner sc = new Scanner(System.in);



	int[][] inv;



	boolean isok(int i, int j) {

		return i >= 0 && i < 10 && j >= 0 && j < 10;

	}



	void setTrans(int d[], int p) { // only for size == 100

		int i = p / 10;

		int j = p % 10;

		Arrays.fill(d, 0);

		int[] di = { 0, 0, 0, 1, -1 };

		int[] dj = { 0, 1, -1, 0, 0 };

		for (int z = 0; z < 5; z++) {

			int ni = i + di[z];

			int nj = j + dj[z];

			if (!isok(ni, nj))

				continue;

			d[10 * ni + nj] = 1;

		}

	}



	void add(int[] to, int[] from) { // only for size==100

		for (int i = 0; i < to.length; i++) {

			to[i] = from[i] ^ to[i];

		}

	}



	void swap(int[] a, int[] b) {

		int piv;

		for (int i = 0; i < 100; i++) {

			piv = a[i];

			a[i] = b[i];

			b[i] = piv;

		}

	}



	void init() { // set inv[][]

		inv = new int[100][100];

		int[][] trans = new int[100][100];

		for (int i = 0; i < 100; i++) {

			setTrans(trans[i], i);



			inv[i][i] = 1;

		}

		for (int i = 0; i < 100; i++) {

			if (trans[i][i] == 0) {

				for (int j = i + 1; j < 100; j++) {

					if (trans[j][i] == 1) {

						swap(trans[i], trans[j]);

						swap(inv[i], inv[j]);

						break;

					}

				}

			}

			for (int j = i + 1; j < 100; j++) {

				if (trans[j][i] == 1) {

					add(trans[j], trans[i]); // ツ湘」ツ三ツ角ツ行ツ療アツ可サ

					add(inv[j], inv[i]);

				}

			}

		}

		for (int i = 0; i < 100; i++) {

			if (trans[99 - i][99 - i] == 0) {

				for (int j = i + 1; j < 100; j++) {

					if (trans[99 - j][99 - i] == 1) {

						swap(trans[99 - i], trans[99 - j]);

						swap(inv[99 - i], inv[99 - j]);

						break;

					}

				}

			}

			for (int j = i + 1; j < 100; j++) {

				if (trans[99 - j][99 - i] == 1) {

					add(trans[99 - j], trans[99 - i]); // ツ妥篠角ツ行ツ療アツ可サ

					add(inv[99 - j], inv[99 - i]);

				}

			}

		}

	}



	int[] ans(int in[]) {

		int[] ret = new int[100];

		for (int i = 0; i < 100; i++) {

			for (int j = 0; j < 100; j++) {

				ret[i] ^= inv[i][j] * in[j];

			}

		}

		return ret;

	}



	void run() {

		int n = sc.nextInt();

		init();

		for (int z = 0; z < n; z++) {

			int in[] = new int[100];

			for (int i = 0; i < 100; i++) {

				in[i] = sc.nextInt();

			}

			int ans[] = ans(in);

			for (int i = 0; i < 10; i++) {

				for (int j = 0; j < 10; j++) {

					if (j != 0) {

						System.out.print(" ");

					}

					System.out.print(ans[i * 10 + j]);

				}

				System.out.println();

			}

		}



	}



	public static void main(String[] args) {

		Main m = new Main();

		m.run();

	}

}