6980. 【2021.02.03冬令營模擬】你的世界(world) Another Solution

ZnPdCo發表於2024-03-14

Problem Description

Input

從檔案 world.in 中讀入資料。

Output

輸出到檔案 world.out 中。

輸出共 T 行,第 i 行表示第 i 組測試資料的答案,如果可行則輸出 Yes,否則輸出 No。

Sample Input Copy

樣例輸入1:
1
2 3
000
000
111
001

樣例輸入2:
1
3 4
0000
0101
0001
1011
0001
1100

樣例輸入3:
1
4 5
11000
01010
00011
10110
00011
11001
11010
10001

Sample Output Copy

樣例輸出1:
Yes

樣例輸出2:
Yes

樣例輸出3:
No

Data Constraint

首先,\(A\gets A\oplus B\),我們的問題就變成了怎麼操作使得一個空矩陣變成新的矩陣 \(A\)


先考慮只能操作行和列,該怎麼做。

如果這張圖是合法的,我們發現對於任意的 \(2\times2\) 子矩陣 \(\begin{bmatrix} a_{0,0} & a_{0,1} \\ a_{1,0} & a_{1,1} \end{bmatrix}\),有 \(a_{0,0}\oplus a_{0,1}\oplus a_{1,0}\oplus a_{1,1}=0\)

我們來證明一下,因為對於操作行和列,一定會操作 \(2\times2\) 子矩陣中的任意兩個,那麼異或結果不變。

所以,我們定義 \(a_{0,0},a_{0,1},a_{1,0},a_{1,1}\) 這類異或結果不變的為固定元素,其餘的為不固定元素。

\(2\times2\) 子矩陣中有固定元素,也就是這個子矩陣被固定了,所以它合法。


存不存在更小的子矩陣呢?比如說 \(1\times1\) 子矩陣。

答案是不存在的,因為對於一個 \(1\times1\) 子矩陣 \(\begin{bmatrix} a_{0,0} \end{bmatrix}\),我們可以隨意修改這個點,所以不存在固定元素,不合法。


考慮加入對角線操作。

如果還是剛剛的 \(2\times2\) 矩陣,我們發現由於對角線操作的加入可以出現形如 \(\begin{bmatrix} 0 & 1 \\ 1 & 1 \end{bmatrix}\)\(\begin{bmatrix} 0 & 0 \\ 0 & 1 \end{bmatrix}\) 等等等等的矩陣,子矩陣中沒有一個元素是固定元素,這個子矩陣是不固定的!

所以考慮更大的子矩陣。


考慮一個 \(4\times4\) 子矩陣,我們發現對於任意的 \(4\times4\) 子矩陣 \(\begin{bmatrix} a_{0,0} & \textcolor{red}{a_{0,1}} & \textcolor{red}{a_{0,2}} & a_{0,3} \\ \textcolor{red}{a_{1,0}} & a_{1,1} & a_{1,2} & \textcolor{red}{a_{1,3}} \\ \textcolor{red}{a_{2,0}} & a_{2,1} & a_{2,2} & \textcolor{red}{a_{2,3}} \\ a_{3,0} & \textcolor{red}{a_{3,1}} & \textcolor{red}{a_{3,2}} & a_{3,3} \\ \end{bmatrix}\),有 \(a_{0,1}\oplus a_{0,2}\oplus a_{1,0}\oplus a_{1,3}\oplus a_{2,0}\oplus a_{2,3}\oplus a_{3,1}\oplus a_{3,2}=0\)。(為了方便我將這些固定元素標紅)

證明顯然:

  • 對於 \(a_{0,0},a_{0,3},a_{3,0},a_{3,3}\),可以進行一個對角線操作,所以這些元素是可以隨便調整的,是不固定元素;
  • 對於 \(a_{0,1},a_{0,2},a_{1,0},a_{1,3},a_{2,0},a_{2,3},a_{3,1},a_{3,2}\),這些元素無法抵消,只能進行對角線同時操作兩個固定元素,所以異或結果不會變化;
  • 對於 \(a_{1,1},a_{1,2},a_{2,2},a_{2,2}\),這些元素可以透過亂搞抵消,具體自己亂搞。

所以這個子矩陣是固定的。

我們繼續發現,不存在比 \(4\times4\) 還小的子矩陣。


所以這道題就很簡單了,列舉矩陣 \(A\) 的子矩陣左上角 \((i,j)\),只需要所有的子矩陣均滿足滿足 \(a_{i,j+1}\oplus a_{i,j+2}\oplus a_{i+1,j}\oplus a_{i+1,j+3}\oplus a_{i+2,j}\oplus a_{i+2,j+3}\oplus a_{i+3,1}\oplus a_{j+3,2}=0\),則這張圖有解。

時間複雜度 \(O(nm)\)


然後這道題就可以開始加強了,比如加入各種新印章,都可以用這種方法輕鬆解決。

#include <cstdio>
#include <chrono>
#include <random>
using namespace std;
using namespace chrono;
#define ll long long
#define N 1010
ll t, n, m;
char a[N][N], b[N][N];
int main() {
	freopen("world.in", "r", stdin);
	freopen("world.out", "w", stdout);
	scanf("%lld", &t);
	while(t--) {
		scanf("%lld %lld", &n, &m);
		for(ll i = 1; i <= n; i++) {
			scanf("%s", a[i]+1);
		}
		for(ll i = 1; i <= n; i++) {
			scanf("%s", b[i]+1);
			for(ll j = 1; j <= m; j++) {
				if(a[i][j] == b[i][j]) a[i][j] = 0;
				else a[i][j] = 1;
			}
		}
		bool flag = 1;
		for(ll i = 1; i <= n - 3; i++) {
			for(ll j = 1; j <= m - 3; j++) {
				if(a[i][j+1] ^ a[i][j+2] ^ a[i+1][j] ^ a[i+1][j+3] ^ a[i+2][j] ^ a[i+2][j+3] ^ a[i+3][j+1] ^ a[i+3][j+2]) {
					printf("No\n");
					flag = 0;
					break;
				}
			}
			if(!flag) break;
		}
		if(flag) printf("Yes\n");
	}
}

相關文章