zoukankan      html  css  js  c++  java
  • CodeForces 663E Binary Table

    Description

    You are given a table consisting of n rows and m columns. Each cell of the table contains either 0 or 1. In one move, you are allowed to pick any row or any column and invert all values, that is, replace 0 by 1 and vice versa.

    What is the minimum number of cells with value 1 you can get after applying some number of operations?

    Input

    The first line of the input contains two integers n and m (1 ≤ n ≤ 20, 1 ≤ m ≤ 100 000) — the number of rows and the number of columns, respectively.

    Then n lines follows with the descriptions of the rows. Each line has length m and contains only digits '0' and '1'.

    Output

    Output a single integer — the minimum possible number of ones you can get after applying some sequence of operations.

    Example

    Input

    3 4
    0110
    1010
    0111
    

    Output

    2
    

    题意

    每次操作可以取反任意一行或一列,问矩阵中最少的1

    题解

    我们观察到n只有20,我们完全可以枚举行的翻转状态,然后对于每一列,如果翻转能获得更少的1就翻转,复杂度为(O(2^nm))

    我们考虑,设某一列一开始的状态是(k),翻转状态为(i),翻转后的状态为(j),显然有

    [i oplus k = j\i = j oplus k ]

    利用这个性质,我们设a[x]为一开始矩阵中x状态的数量,b[x]为这一列状态为x时,(min(num[1],num[0])),因为列可以随意翻转,以获得更少的1,这样这样累加就可以获得翻转状态为i时,矩阵中所含的最少的1的数量,全部求出后取min就可以了.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    void fwt(ll a[], int len, int op) {
        for (int h = 2; h <= len; h <<= 1) {
            for (int j = 0; j < len; j += h) {
                for (int k = j; k < j + h / 2; k++) {
                    ll u = a[k], t = a[k + h / 2];
                    a[k] = u + t;
                    a[k + h / 2] = u - t;
                    if (op == -1) {
                        a[k] /= 2; a[k + h / 2] /= 2;
                    }
                }
            }
        }
    }
    const int N = 2e6;
    char ch[20][100050];
    ll a[N], b[N];
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) {
            scanf("%s", ch[i]);
        }
        int len = 1 << n;
        for (int i = 0; i < m; i++) {
            int x = 0;
            for (int j = 0; j < n; j++) {
                x += (ch[j][i] - '0') << j;
            }
            a[x]++;
        }
        for (int i = 1; i < len; i++) {
            b[i] = b[i >> 1] + (i & 1);
        }
        for (int i = 0; i < len; i++) {
            b[i] = min(b[i], n - b[i]);
        }
        fwt(a, len, 1);
        fwt(b, len, 1);
        for (int i = 0; i < len; i++) {
            a[i] = a[i] * b[i];
        }
        fwt(a, len, -1);
        ll ans = 1e18;
        for (int i = 0; i < len; i++) {
            ans = min(ans, a[i]);
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    layui table表格可搜索下拉框
    mysql重置密码
    纯js代码生成可搜索选择下拉列表
    ORACLE视图简单创建和使用
    zTree多条件模糊查询
    zTree模糊搜索,显示全部节点和高亮显示
    让我们来写一个v-model吧
    使用nodejs爬取静态网页数据
    vue-cli引用vant使用rem自适应
    前端以BASE64码的形式上传图片
  • 原文地址:https://www.cnblogs.com/artoriax/p/12190419.html
Copyright © 2011-2022 走看看