• Bzoj3517 翻硬币题解 解异或方程组


    3517: 翻硬币

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 281  Solved: 211
    [Submit][Status][Discuss]

    Description

    有一个nn列的棋盘,每个格子上都有一个硬币,且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。

       上来一看,第一反应,异或数学题,想了半天如何异或也没想出来,问呵呵酵母菌,他说他觉得是图论WTF?!图论有几个O(n)算法能在这道题用上的。

      于是乎看了一眼题解:解异或方程组……

      一个点最多翻一遍,这话不用再说了吧……

      让我们先从都翻为0开始说起

      我们设x[i][j]为第i,j个点是否要翻,a[i][j]为该点初始状态,则x[1][j]^x[2][j]^……^x[n][j]^x[i][1]^x[i][2]^x[i][m]^x[i][j]=a[i][j]。

      我们把第i行和第j列所有的点按照上式列出方程组并合并, 由于n为偶数,则可以化为:

        x[i][j]=a[1][j]^a[2][j]^……^a[n][j]^a[i][1]^a[i][2]^……^a[i][m]^a[i][j]。

      那么我们只要对于每一行,每一列n^2预处理出他们的异或和再相加就好了。

      至于都为1吗?由于n是偶数,我们只要把每一个点是否翻的状态取反就是答案。

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 #include <algorithm>
     7 #include <cmath>
     8 #include <map>
     9 #define N 1005
    10 using namespace std;
    11 int n,a[N][N];
    12 char b[N];
    13 int sum[2][N];
    14 int main()
    15 {
    16     scanf("%d",&n);
    17     for(int i=1;i<=n;i++)
    18     {
    19         scanf("%s",b+1);
    20         for(int j=1;j<=n;j++)
    21         {
    22             a[i][j]=b[j]-'0';
    23         }
    24     }
    25     for(int i=1;i<=n;i++)
    26     {
    27         for(int j=1;j<=n;j++)
    28         {
    29             sum[0][i]^=a[i][j];
    30             sum[1][j]^=a[i][j];
    31         }
    32     }
    33     int ans=0;
    34     for(int i=1;i<=n;i++)
    35     {
    36         for(int j=1;j<=n;j++)
    37         {
    38             int t=sum[0][i]^sum[1][j];
    39             t^=a[i][j];
    40             ans+=t;
    41         }
    42     }
    43     ans=min(ans,n*n-ans);
    44     printf("%d
    ",ans);
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    MOS
    1- Bluetooth开发
    1- Bluetooth
    MCU 51-10 Infrared Communication
    1- STM32 HAL库学习 GPIO配置点亮LED灯
    MCU 51-9 DS18B20 Temperature Sensor
    MCU 51-8 AD/DA
    C语言讲义——变量(variable)
    C语言讲义——注释
    C语言讲义——“编译、链接”
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7674354.html
Copyright © 2020-2023  润新知