1. 题目
2. 题解
一开始写的 4 维高斯消元,想象力崩溃。。。
最后还是没写出来,放弃治疗了,写了个四维转二维的,就过了。
异或方程其实和普通方程是一样的。
异或运算的一些规律和加减乘除都差不多,可以自行百度。
怎么列出方程呢?
设 $ans(i,j)$表示位置 (i,j) 是否选择,为 1 表示选,为 0 表示不选。
设 $g(i,j,k,l)$表示当选择了位置 (i,j),位置 (k,l) 是否会受到影响,1 表示有影响,0 表示无影响。
设输入的矩阵为 a
那么 $a(i,j)$需要等于 $ans(x,y)×g(x,y,i,j)$的异或和。
可以得到 30 个这样的方程,30 个未知数,解即可。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int t,g[50][50],ans[50];
int main()
{
scanf("%d",&t);
for(int cnt=1;cnt<=t;cnt++,memset(g,0,sizeof(g)),memset(ans,0,sizeof(ans)))
{
for(int i=0;i<5;i++)
for(int j=1;j<=6;j++)
{
g[i*6+j][i*6+j]=1;
if(i>0)g[i*6+j][(i-1)*6+j]=1;if(i<4)g[i*6+j][(i+1)*6+j]=1;
if(j>1)g[i*6+j][i*6+j-1]=1;if(j<6)g[i*6+j][i*6+j+1]=1;
}
for(int i=1;i<=30;i++)scanf("%d",&g[i][0]);
for(int i=1;i<=30;i++)
{
for(int j=i+1;j<=30;j++)if(g[j][i]){swap(g[i],g[j]);break;}
for(int j=i+1;j<=30;j++)
if(g[j][i])for(int k=0;k<=30;k++)g[j][k]^=g[i][k];
}
for(int i=30;i>=1;i--)
{
ans[i]=g[i][0];
for(int j=i+1;j<=30;j++)ans[i]^=(ans[j]&g[i][j]);
}
printf("PUZZLE #%d\n",cnt);
for(int i=0;i<5;i++,printf("\n"))
for(int j=1;j<=6;j++)
printf("%d ",ans[i*6+j]);
}
return 0;
}
0 条评论