说在前面
并没有什么想说的,但是要保持格式=w=
题目
题面
有一个n行n列的棋盘,每个格子上都有一个硬币,且n为偶数。每个硬币要么是正面朝上,要么是反面朝上。每次操作你可以选定一个格子(x,y),然后将第x行和第y列的所有硬币都翻面。求将所有硬币都变成同一个面最少需要的操作数。
数据范围:n不超过1000
输入输出格式
输入格式:
第一行包含一个正整数n。
接下来n行,每行包含一个长度为n的01字符串,表示棋盘上硬币的状态。
输出格式:
仅包含一行,为最少需要的操作数。
解法
一开始看到这道题,me毫无思路
然后发现,要翻的一定要被翻奇数次,不翻的一定要被翻偶数次
然后发现如果把任意两行(或两列)交换不影响答案
然后联想到了异或方程,然后就没有然后了(于是去看了题解)
看完之后发现,这道题和me之前做过的一道题很像!
现在使用
x[i][j]
x
[
i
]
[
j
]
来表示位于
i
i
行列的棋子是否翻动,
a[i][j]
a
[
i
]
[
j
]
表示原来的状态
现在假设我们把所有的硬币都翻成
0
0
,那么可以写出方程:
^
...
.
.
.
^
x[n][j]
x
[
n
]
[
j
]
^
x[i][1]
x
[
i
]
[
1
]
^
...
.
.
.
^
x[i][j−1]
x
[
i
]
[
j
−
1
]
^
x[i][j+1]
x
[
i
]
[
j
+
1
]
^
...
.
.
.
^
x[i][M]
x
[
i
]
[
M
]
^
a[i][j]=0
a
[
i
]
[
j
]
=
0
(注意式子里
x[i][j]
x
[
i
]
[
j
]
这一项只出现一次),然后我们把
a[i][j]
a
[
i
]
[
j
]
移动到等式右边
然后,我们把除了(i,j)的 第i行的所有式子 以及 第j列的所有式子,都和这个式子联立一下,发现等式左边只会剩下 x[i][j] x [ i ] [ j ] (显然,因为保证n为偶数, x[i][k] x [ i ] [ k ] 会在所有的 x[i][?] x [ i ] [ ? ] 中出现一次,总共出现n次所以就消掉了。而 x[i][j] x [ i ] [ j ] 会出现 2∗n−1 2 ∗ n − 1 次,于是留了下来),然后等式右边就是 a[i][?] a [ i ] [ ? ] 以及 a[?][j] a [ ? ] [ j ] 的异或和,也就是「第i行的异或和」^「第j列的异或和」^「(i,j)原来的状态」
然后要把所有棋子全部翻成1,其实就是把所有的x取反。
很明显,各行各列的异或和可以在输入的时候就处理完毕,然后这题就做完了
下面是自带大常数的代码
代码?什么代码?me貌似还没有写代码 (~ ̄▽ ̄)
(对,你没有看错,嘴巴AC选手在此)
小结一下
me有在上面提到,和这道题很类似的一道题,题目大意是这样的:
给出一个N行M列的矩阵(长宽不超过200),每个格子都可以填0或1,要求填完之后满足以下要求:每个格子与其边相邻的格子 异或和为0,且至少有一个格子为1(不能全0)。输出任意一种方案,题目保证有解
这道题是这样的,可以发现一个性质,如果确定了第一行的所有数字,那么为了满足第一行的要求,第二行也就随之确定了,以此类推,整个矩阵都确定了。于是我们可以假设第1行第i列的格子填法为 x[i] x [ i ] ,那么可以用异或式表示出矩阵的每一个格子(比如 x[1][1] x [ 1 ] [ 1 ] ^ x[1][2] x [ 1 ] [ 2 ] ^ x[2][1]=0⟹x[2][1]=x[1][1] x [ 2 ] [ 1 ] = 0 ⟹ x [ 2 ] [ 1 ] = x [ 1 ] [ 1 ] ^ x[1][2] x [ 1 ] [ 2 ] ),以此类推,把第M+1行也这样表示出来。因为第M+1行不存在,于是这一行全部为0,由此可以得到N个方程,高斯消元解方程就可以了。(如果出现了自由元,全部设为1即可,题目保证有解)
这两道题的做法可以说是比较相似了,都是异或之后需要满足一些条件,然后把每个位置选1还是选0设成未知数然后解方程。感觉这个方法应该对某类型的题都适用