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;
}

分享至ヾ(≧∇≦*)ゝ:
分类: 所有

XZYQvQ

炒鸡辣鸡的制杖蒟蒻一枚QvQ

发表评论

电子邮件地址不会被公开。 必填项已用*标注

你是机器人吗? =。= *