【洛谷P3164】和谐矩阵
题目
题目链接:https://www.luogu.com.cn/problem/P3164
给出 \(n,m\),输出任意一个 \(n\times m\) 的 01 矩阵满足矩阵中任意元素与其四周元素的权值和均为偶数。
\(n,m\leq 40\)。
思路
挺显然的高斯消元。太久没敲了,就当做练练手吧。
对于矩阵中的一个点 \((x,y)\),就是要我们求出一种方案满足 \(a[x][y]\ \operatorname{xor}\ a[x-1][y]\ \operatorname{xor}\ a[x+1][y]\ \operatorname{xor}\ a[x][y-1]\ \operatorname{xor}\ a[x][y+1]=0\)。
那么我们对于每一个点 \((x,y)\),我们可以列出一个形如 \(a_1x_1\ \operatorname{xor}\ a_2x_2\ \operatorname{xor}\ ...\ \operatorname{xor}\ a_{nm}x_{nm}=0\) 的方程。其中如果一个点与 \((x,y)\) 相邻或就是 \((x,y)\),那么该位置的系数 \(a=1\),否则 \(a=0\)。
然后就是高斯消元板子了。
时间复杂度 \(O\)\(\Large{(}\)\((nm)^3\)\(\Large{)}\)。显然跑不过。
我们发现,题目要求是 01 矩阵,每一位的取值就只有 0 或 1。所以可以用 \(\operatorname{bitset}\) 搞搞就可以了。时间复杂度 \(O(\frac{(nm)^3}{32})\)。
代码
#include <cstdio>
#include <bitset>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=50;
const int dx[]={0,0,0,-1,1},dy[]={0,-1,1,0,0};
int n,m,id[N][N],ans[N*N];
bitset<N*N> a[N*N];
void gauss()
{
for (int i=1;i<=n*m;i++)
{
for (int j=i;j<=n*m;j++)
if (a[j][i]>0)
{
swap(a[i],a[j]);
break;
}
if (!a[i][i]) ans[i]=1;
for (int j=i+1;j<=n*m;j++)
if (a[j][i]) a[j]^=a[i];
}
for (int i=n*m;i>=1;i--)
for (int j=i+1;j<=n*m;j++)
ans[i]^=(ans[j]*a[i][j]);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
id[i][j]=(i-1)*m+j;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
for (int k=0;k<=4;k++)
{
int x=i+dx[k],y=j+dy[k];
if (x<1 || y<1 || x>n || y>m) continue;
a[id[i][j]][id[x][y]]=1;
}
}
gauss();
for (int i=1;i<=n*m;i++)
{
printf("%d ",ans[i]);
if (i%m==0) putchar(10);
}
return 0;
}