为什么可以跑n立方,我也不知道,反正就是可以。
模2意义的,据说每一行可以存一个bitset,会比用bool更快(快32倍?)。
本题告诉我们一个道理:
高斯消元之后,每个变量的含义不变(虽然交换了两行,但是实际上那个位置的向量还是表示那个单元),不需要复原。
每个变量要前往的目标状态不一样。注意非自由变量要用新的右边来确定值。
并不是所有的自由变量都在右下角,有可能有完全空的列。
也可以在给每行赋值秩的同时指定该列是秩为第几的列,0表示空列。
可以在消元的同时对自由变量进行赋值,非自由变量立刻由他决定。但是感觉很扯。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,r;
inline int antii(int id) {
int res=((id+m-1)/m);
return res;
}
inline int antij(int id) {
int res=id%m;
if(res==0)
res=m;
return res;
}
inline int id(int,int);
bool tx[1800]= {};
bool allzero[1800]= {};
bool outtm[50][50]= {};
bool out() {
int have1=0;
for(int id=1; id<=n*m; id++) {
outtm[antii(id)][antij(id)]=tx[id];
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
if(outtm[i][j]^outtm[i-1][j]^outtm[i+1][j]^outtm[i][j-1]^outtm[i][j+1]) {
return false;
}
if(outtm[i][j])
have1=1;
}
}
if(!have1)
return false;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++)
printf("%d%c",(int)outtm[i][j]," \n"[j==m]);
}
return true;
//高斯消元后,每个变量的目标已经改变了,不需要复原!!!
}
namespace Gauss_Jordan_Elimination {
const int MAXN=1800;
const int MAXM=1800;
bool a[MAXN][MAXM+1];
bool ans[MAXN];
//返回增广矩阵的秩,-1表示无解
int gauss_jordan(int n,int m) {
int r=0;
for(int i=1; i<=m; i++) {
//当前是第i列
int mx=-1;
//从当前秩的下一行开始往下数
for(int j=r+1; j<=n; j++)
if(a[j][i]) {
mx=j;
break;
}
if(mx==-1) {
//该列全0,被跳过
continue;
}
r++;
//增加一个线性基,当前秩增加
if(mx!=r) {
//需要交换
for(int j=1; j<=m+1; j++)
//m+1表示增广矩阵
swap(a[r][j],a[mx][j]);
//交换行
}
for(int j=1; j<=n; j++) {
//枚举每一行
if(j!=r&&a[j][i]) {
//消去除了r以外的其他行
//该行系数是当前列的tmp倍
for(int k=i; k<=m+1; k++) {
//把当前列对应行位置扩大tmp倍,然后用每个元素减去,由高斯约当的过程,左边的绝对是0
a[j][k]^=a[r][k];
}
}
}
}
return r;
}
}
using namespace Gauss_Jordan_Elimination;
inline int id(int i,int j) {
if(i>=1&&i<=n&&j>=1&&j<=m)
return (i-1)*m+j;
else
return 0;
}
int dx[4]= {-1,1,0,0};
int dy[4]= {0,0,-1,1};
void dfs(int x,bool have1) {
if(x==0) {
if(have1) {
if(out()) {
exit(0);
}
}
return;
}
if(allzero[x]) {
tx[x]=1;
dfs(x-1,1);
tx[x]=0;
dfs(x-1,have1);
} else {
bool v=a[x][n*m+1];
for(int i=x+1; i<=n*m; i++) {
v^=a[x][i]&tx[i];
}
tx[x]=v;
dfs(x-1,have1|v);
}
}
int main() {
scanf("%d%d",&n,&m);
{
{
memset(a,0,sizeof(a));
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
int tid=id(i,j);
a[tid][tid]=1;
for(int k=0; k<4; k++) {
int ttid=id(i+dx[k],j+dy[k]);
if(ttid) {
a[tid][ttid]=1;
}
}
}
}
r=gauss_jordan(n*m,n*m);
for(int i=1; i<=n*m; i++) {
allzero[i]=1;
for(int j=1; j<=n*m; j++) {
if(a[i][j]) {
allzero[i]=0;
break;
}
}
}
dfs(n*m,0);
}
}
}