给定一个 的 01 矩阵 ,和两个长 的非负整数数组 。请构造两个长 的 01 数组 ,满足:
- 都有 ;
- 都有 ;
,。
怎么这么笨。
关键步骤:先通过列翻转将第一行变成 。
不难发现,将 和 全部取反不影响合法性,所以可以钦定 。接下来由于 ,所以列翻转次数()也 。
那么对于一行 ,若此时 则一定有 ,否则一定有 。
故 就确定了,那么 也可以直接确定了。
再判一下合法性即可。
时间复杂度 ,代码如下:
#include <iostream>
#include <cstdio>
using namespace std;
const int S=1005;
int n;
char a[S][S];
int cnta[S],cntb[S];
int ra[S],rb[S];
inline void slove()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
for(int j=n;j>=1;j--) a[i][j]=a[i][j-1]-'0';
}
for(int i=1;i<=n;i++) cin>>cntb[i];
for(int i=1;i<=n;i++) cin>>cnta[i];
for(int i=1;i<=n;i++)
{
ra[i]=a[1][i];
for(int j=1;j<=n;j++) a[j][i]^=ra[i];
}
for(int i=1;i<=n;i++)
{
int cnt=0;
for(int j=1;j<=n;j++) cnt+=a[i][j];
rb[i]=cnt>=(n+1)/2;
for(int j=1;j<=n;j++) a[i][j]^=rb[i];
}
for(int i=1;i<=n;i++)
{
int cnt=0;
for(int j=1;j<=n;j++) cnt+=a[j][i];
bool fl=cnt!=cnta[i];
ra[i]^=fl;
for(int j=1;j<=n;j++) a[j][i]^=fl;
}
bool fl=true;
for(int i=1;i<=n;i++)
{
int cnt=0;
for(int j=1;j<=n;j++) cnt+=a[j][i];
fl&=cnt==cnta[i];
cnt=0;
for(int j=1;j<=n;j++) cnt+=a[i][j];
fl&=cnt==cntb[i];
}
if(!fl) cout<<"No\n";
else
{
cout<<"Yes\n";
for(int i=1;i<=n;i++) cout<<rb[i];cout<<'\n';
for(int i=1;i<=n;i++) cout<<ra[i];cout<<'\n';
}
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T-->0) slove();
return 0;
}