[Luogu P3164] [BZOJ 3503] [CQOI2014]和谐矩阵

版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/83795153

洛谷传送门

BZOJ传送门

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:

4 4

输出样例#1:

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

说明

数据范围

1 m , n 40 1 \le m, n \le 40

解题分析

首先我们可以暴力高斯消元, 因为是异或方程组, 可以用 b i t s e t bitset 优化,复杂度是 O ( ( n m ) 3 32 ) O(\frac{(nm)^3}{32}) , 的确能过…

然而这里有一种更优雅的写法: 我们发现只要确定第一行的元素就可以确定整个表的元素, 而整个表有合法解的必要条件为第 n + 1 n+1 行元素递推出来全部为 0 0 。那么我们先 O ( n m ) O(nm) 递推出第 n + 1 n+1 行元素对应的第一行的元素组成, 这样就可以列出 m m m m 元方程, 进而解出得到第一行的元素, 最后再递推一次即可。

总复杂度 O ( m 3 ) O(m^3)

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstdlib>
#include <bitset>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 45
#define ll long long


int n, m;
ll tran[MX][MX];
std::bitset <MX> mat[MX], ans[MX];


void Gauss()
{
	for (R int i = 1; i <= m; ++i)
	{
		for (R int j = i; j <= m; ++j)
		if (mat[j][i]) {std::swap(mat[j], mat[i]); break;}
		if (!mat[i][i]) continue;
		for (R int j = i + 1; j <= m; ++j) if (mat[j][i]) mat[j] ^= mat[i];
	}
	for (R int i = m; i; --i)
	{
		ans[1][i] = mat[i][i] ? mat[i][m + 1] : 1;
		if (ans[1][i]) for (R int j = 1; j < i; ++j) if (mat[j][i]) mat[j][m + 1] = !mat[j][m + 1];
	}
}


int main(void)
{
	scanf("%d%d", &n, &m);
	for (R int i = 1; i <= m; ++i) tran[1][i] = 1ll << i;
	for (R int i = 2; i <= n + 1; ++i)
	for (R int j = 1; j <= m; ++j)
	tran[i][j] = tran[i - 1][j - 1] ^ tran[i - 1][j] ^ tran[i - 1][j + 1] ^ tran[i - 2][j];
	for (R int i = 1; i <= m; ++i)
	for (R int j = 1; j <= m; ++j) mat[i][j] = (tran[n + 1][i] >> j) & 1;
	Gauss();
	for (R int i = 2; i <= n; ++i)
	for (R int j = 1; j <= m; ++j)
	ans[i][j] = ans[i - 1][j - 1] ^ ans[i - 1][j] ^ ans[i - 1][j + 1] ^ ans[i - 2][j];
	for (R int i = 1; i <= n; ++i)
	{
		for (R int j = 1; j <= m; ++j) printf("%d ", (int)ans[i][j]);
		puts("");
	}
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/83795153
今日推荐