1. 程式人生 > 實用技巧 >【CF1451F】Nullify The Matrix

【CF1451F】Nullify The Matrix

題目

題目連結:https://codeforces.com/problemset/problem/1451/F
給出一個 \(n\times m\) 的網格,每個格子上有一個非負數。
兩人輪流操作,每次操作選擇一個數字大於 \(0\) 格子 \((x,y)\) 開始,將 \((x,y)\) 減去一個正整數,並且修改完後 \((x,y)\) 依然非負。
然後選擇一條從 \((x,y)\) 開始只往右和往下的路徑,到任意格子結束,並且將除 \((x,y)\) 以外所有格子修改為一個非負數。
最先無法操作的人獲勝。問先手是否必勝。
\(Q\leq 10,n,m,\leq 100\)

思路

考慮橫縱座標之和相同的格子形成的一條條斜線,如果選擇了格子 \((x,y)\)

,那麼它可以控制到所有 \(x+y<k\) 的斜線 \(k\) 的異或和。
找到第一個異或和不為 \(0\) 的斜線,根據 NIM 遊戲的證明我們知道,只要選擇異或和中最高位為 \(1\) 的那一個將它減小至異或和,這樣就使得異或和變為 \(0\)
除此之外,我們操作了這個格子之後還可以改變後面所有斜線的異或和,所以如果存在一條斜線的異或和不為 \(0\),我們就可以通過一次操作把所有斜線的異或和變為 \(0\)
接下來後手操作一定會變回存在一條斜線異或和不為 \(0\) 的情況,而目標狀態異或和為 \(0\),所以我們只需要判斷初始狀態是否存在一條斜線的異或和不為 \(0\) 即可。
時間複雜度 \(O(Qnm)\)

程式碼

#include <bits/stdc++.h>
using namespace std;

const int N=110;
int Q,n,m,x,xors[N*2];

int main()
{
	scanf("%d",&Q);
	while (Q--)
	{
		memset(xors,0,sizeof(xors));
		scanf("%d%d",&n,&m);
		for (int i=1;i<=n;i++)
			for (int j=1;j<=m;j++)
			{
				scanf("%d",&x);
				xors[i+j]^=x;
			}
		x=0;
		for (int i=1;i<=n+m;i++)
			x+=xors[i];
		if (x) printf("Ashish\n");
			else printf("Jeel\n");
	}
	return 0;
}