bzoj 3503(解异或方程组)

3503: [Cqoi2014]和谐矩阵

Time Limit: 10 Sec   Memory Limit: 128 MBSec   Special Judge
Submit: 897   Solved: 411
[ Submit][ Status][ Discuss]

Description

我们称一个由0和1组成的矩阵是和谐的,当且仅当每个元素都有偶数个相邻的1。一个元素相邻的元素包括它本
身,及他上下左右的4个元素(如果存在)。
给定矩阵的行数和列数,请计算并输出一个和谐的矩阵。注意:所有元素为0的矩阵是不允许的。

Input

输入一行,包含两个空格分隔的整数m和n,分别表示矩阵的行数和列数。

Output


输出包含m行,每行n个空格分隔整数(0或1),为所求矩阵。测试数据保证有解。

Sample Input

4 4

Sample Output

0 1 0 0
1 1 1 0
0 0 0 1
1 1 0 1

数据范围

1 <=m, n <=40


解题思路:首先可以知道第一行确定后下面的都可以确定了,

那么可以递推让后用第一行表示最后一行,这样就列出了n个

方程,于是高斯消元,题目中说全0的不算,那么对于那些

自由元就可以设为1。


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m;
int g[60][60],f[60][60][60],h[60][60],ans[60];
bool b[60];


inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}


void guass()
 {
  int p=1; int x=1;
  while (x<=n)
  {
   int j=0;
   for (int i=p;i<=n;++i)
   if (g[i][x]!=0)
{
j=i;
break;
}
 if (j==0)
       {
        ans[x]=1; b[x]=false;
        for (int i=1;i<=p-1;++i)
        if (g[i][x]==1)
         {
          g[i][x]=0; g[i][n+1]^=1; 
 }
++x;
  }else
   {
     for (int i=1;i<=n+1;++i) swap(g[j][i],g[p][i]);
     for (int i=p+1;i<=n;++i) 
      if (g[i][x]==1)
       {
        for (int k=x;k<=n+1;++k) g[i][k]^=g[p][k];
}
     ++p; ++x;
   }
}
--x;
for (int i=p-1;i>=1;--i)
{
while (b[x]==false)--x; 
ans[x]=g[i][n+1]; b[x]=false;
for (int j=i-1;j>=1;--j)
if (g[j][x]!=0)g[j][n+1]^=ans[x],g[j][x]=0; 
}
 }


int main()
{
memset(b,true,sizeof(b));
m=read(); n=read();
for (int i=1;i<=n;++i) f[1][i][i]=1;
    for (int i=2;i<=m+1;++i)
     for (int j=1;j<=n;++j)
      {
      for (int k=1;k<=n;++k)
      {
      f[i][j][k]=f[i-1][j-1][k]^f[i-1][j][k]^f[i-1][j+1][k]^f[i-2][j][k];
}
 }
for(int i=1;i<=n;++i)
for (int j=1;j<=n;++j) 
 g[i][j]=f[m+1][i][j];
guass();
for (int i=1;i<=n;++i) h[1][i]=ans[i];
for (int i=2;i<=m;++i)
{
for (int j=1;j<=n;++j)
h[i][j]=h[i-1][j]^h[i-1][j+1]^h[i-1][j-1]^h[i-2][j];
}
for (int i=1;i<=m;++i)
{
  for (int j=1;j<=n-1;++j)
   printf("%d ",h[i][j]);
  printf("%d\n",h[i][n]);
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值