1. 程式人生 > >[Luogu P3164] [BZOJ 3503] [CQOI2014]和諧矩陣

[Luogu P3164] [BZOJ 3503] [CQOI2014]和諧矩陣

洛谷傳送門

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("");
	}
}