BZOJ - 3517 翻硬币(异或)
2016-12-03 03:50
155 查看
题目:
Description
有一个n行n列的棋盘,每个格子上都有一个硬币,且n为偶数。每个硬币要么是正面朝上,要么是反面朝上。每次操作你可以选定一个格子(x,y),然后将第x行和第y列的所有硬币都翻面。求将所有硬币都变成同一个面最少需要的操作数。
Input
第一行包含一个正整数n。
接下来n行,每行包含一个长度为n的01字符串,表示棋盘上硬币的状态。
Output
仅包含一行,为最少需要的操作数。
Sample Input
Sample Output
Hint
【样例说明】
对(2,3)和(3,1)进行操作,最后全变成1。
【数据规模】
对于100%的数据,n ≤ 1,000。
分析:(以下6个数组都是0-1数组,S也是0或1)
假设输入矩阵是num[i][j],第i行的异或和是row[i],第j行的异或和是col[j](0<=i<n,0<=j<n)
要求的矩阵是xnum[i][j],第i行的异或和是xrow[i],第j行的异或和是xcol[j],n*n个xnum[i][j]的异或和为S
因为不知道最后是全部变成1还是全部变成0,所以有2种情况
第一种情况:
那么根据题意,num[i][j]^xrow[i]^xcol[j]^xnum[i][j]=0 ------(1)
将(1)式中的j取遍0至n-1,再将n个式子求异或,根据异或的交换性和结合性从而化简得到:
row[i]^(xrow[i]*n%2)^S^xrow[i]=0
因为n是偶数所以row[i]^S^xrow[i]=0 ------(2)
同理col[j]^S^xcol[j]=0 ------(3)
(1)(2)(3)式的异或和为num[i][j]^row[i]^col[j]^xnum[i][j]=0
即xnum[i][j]=num[i][j]^row[i]^col[j]
第二种情况:
与第一种情况同理,xnum[i][j]=num[i][j]^row[i]^col[j]^1
第一种情况和第二种情况刚好完全互补,其中1较少的那种就是结果
无论是第一种还是第二种,由num计算xnum的方法和由xnum计算num的方法是一样的,这是一种高度的对称性,这一点,和点亮所有的灯十分相似
代码:
Description
有一个n行n列的棋盘,每个格子上都有一个硬币,且n为偶数。每个硬币要么是正面朝上,要么是反面朝上。每次操作你可以选定一个格子(x,y),然后将第x行和第y列的所有硬币都翻面。求将所有硬币都变成同一个面最少需要的操作数。
Input
第一行包含一个正整数n。
接下来n行,每行包含一个长度为n的01字符串,表示棋盘上硬币的状态。
Output
仅包含一行,为最少需要的操作数。
Sample Input
4 0101 1000 0010 0101
Sample Output
2
Hint
【样例说明】
对(2,3)和(3,1)进行操作,最后全变成1。
【数据规模】
对于100%的数据,n ≤ 1,000。
分析:(以下6个数组都是0-1数组,S也是0或1)
假设输入矩阵是num[i][j],第i行的异或和是row[i],第j行的异或和是col[j](0<=i<n,0<=j<n)
要求的矩阵是xnum[i][j],第i行的异或和是xrow[i],第j行的异或和是xcol[j],n*n个xnum[i][j]的异或和为S
因为不知道最后是全部变成1还是全部变成0,所以有2种情况
第一种情况:
那么根据题意,num[i][j]^xrow[i]^xcol[j]^xnum[i][j]=0 ------(1)
将(1)式中的j取遍0至n-1,再将n个式子求异或,根据异或的交换性和结合性从而化简得到:
row[i]^(xrow[i]*n%2)^S^xrow[i]=0
因为n是偶数所以row[i]^S^xrow[i]=0 ------(2)
同理col[j]^S^xcol[j]=0 ------(3)
(1)(2)(3)式的异或和为num[i][j]^row[i]^col[j]^xnum[i][j]=0
即xnum[i][j]=num[i][j]^row[i]^col[j]
第二种情况:
与第一种情况同理,xnum[i][j]=num[i][j]^row[i]^col[j]^1
第一种情况和第二种情况刚好完全互补,其中1较少的那种就是结果
无论是第一种还是第二种,由num计算xnum的方法和由xnum计算num的方法是一样的,这是一种高度的对称性,这一点,和点亮所有的灯十分相似
代码:
#include <iostream> using namespace std; int num[1001][1001], row[1001], col[1001]; int main() { int n, sum = 0; cin >> n; char c; for (int i = 0; i < n; i++)row[i] = col[i] = 0; for (int i = 0; i < n; i++)for (int j = 0; j < n; j++) { cin >> c; num[i][j] = c - '0'; row[i] += num[i][j], col[j] += num[i][j]; } for (int i = 0; i < n; i++)for (int j = 0; j < n; j++) sum += (row[i] + col[j] + num[i][j]) % 2; cout << ((sum * 2>n*n) ? n*n - sum : sum) << endl; return 0; }
相关文章推荐
- [BZOJ3517]-翻硬币-异或方程
- BZOJ 翻硬币-(异或和)
- BZOJ3517 翻硬币
- bzoj 3517: 翻硬币
- BZOJ 3517: 翻硬币
- bzoj 3517: 翻硬币
- [BZOJ 3517]翻硬币
- 【LNOI/JLOI/SHOI2016】【BZOJ4561】圆的异或并
- BZOJ 3563 DZY Loves Chinese / BZOJ 3569 DZY Loves Chinese II 随机化+高斯消元解异或方程组
- BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
- BZOJ_3261_最大异或和_可持久化trie
- [Bzoj3233][Ahoi2013]找硬币[基础DP]
- bzoj 1042: [HAOI2008]硬币购物
- Bzoj1042: [HAOI2008]硬币购物
- BZOJ 4017&&2017 icpc 西安G 区间异或和
- BZOJ2115 线性基 对于异或环的处理
- [Trie树] BZOJ3689: 异或之
- BZOJ4888 [Tjoi2017]异或和 【树状数组】
- 【BZOJ3656】异或【扩展Lucas】【线性无关】
- 【BZOJ-1042】硬币购物 容斥原理 + 完全背包