​传送门​

发现每一行,每一列如果操作,必然是奇数次操作

否则,偶数次的操作和不操作没有区别。

而且,当 a i , j = = b i , j a_{i,j}==b_{i,j} ai,j==bi,j时每个格子被操作偶数次

当 a i , j ! = b i , j a_{i,j}!=b_{i,j} ai,j!=bi,j时这个格子被操作奇数次

设 r o w i row_i rowi为第 i i i行操作次数, l i e j lie_j liej为第 j j j列操作的次数

那么 a i , j a_{i,j} ai,j的操作次数等于 r o w i + l i e j row_i+lie_j rowi+liej

假如我们枚举第一行的操作次数,那么由于 a 1 , 1 a_{1,1} a1,1到 a 1 , n a_{1,n} a1,n(第一行)的操作次数已知

那么不久可以直接解得 c o l 1 col_1 col1到 c o l n col_n coln吗

然后由于 a 1 , 1 a_{1,1} a1,1到 a n , 1 a_{n,1} an,1(第一列)的操作次数已知,不久可以解得 r o w 2 row_2 row2到 r o w n row_n rown吗

现在已知 r o w row row和 l i e lie lie,叫你去判断每个格子是否合法不会判断吗??

所以只需要分第一行操作偶数次和奇数次讨论一下就好了。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn =1009;
const int mod = 1e9+7;
int n,t;
int row[maxn],lie[maxn];
char a[maxn][maxn],b[maxn][maxn];
bool ok()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if( a[i][j]==b[i][j]&&(row[i]+lie[j])%2==0 ) continue;
else if( a[i][j]!=b[i][j]&&(row[i]+lie[j])%2==1 ) continue;
else return false;
return true;
}
signed main()
{
int t; cin >> t;
while( t-- )
{
cin >> n;
for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
for(int i=1;i<=n;i++) scanf("%s",b[i]+1);
//第一行不操作
row[1] = 0;
for(int i=1;i<=n;i++)
if( a[1][i]==b[1][i] ) lie[i] = 0;
else lie[i] = 1;
for(int i=2;i<=n;i++)
if( a[i][1]==b[i][1] ) row[i] = lie[1];
else row[i] = lie[1]^1;
if( ok() ) { printf("YES\n"); continue; }
row[1] = 1;
for(int i=1;i<=n;i++)
if( a[1][i]==b[1][i] ) lie[i] = 1;
else lie[i] = 0;
for(int i=2;i<=n;i++)
if( a[i][1]==b[i][1] ) row[i] = lie[1];
else row[i] = lie[1]^1;
if( ok() ) printf("YES\n");
else printf("NO\n");
}
}