CROC 2016 - Final Round [Private, For Onsite Finalists Only] C. Binary Table FWT
C. Binary Table
题目连接:
http://codeforces.com/problemset/problem/662/C
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.
Sample Input
3 4
0110
1010
0111
Sample Output
2
Hint
题意
给你一个nm的01矩阵,然后每次操作:你可以挑选任意的某一行或者某一列翻转,然后你需要使得整个矩阵的1的数量尽可能少,问你最少数量是多少。
题解:
首先2^nm这个算法很简单:暴力枚举横着怎么翻转,然后每一列O(1)判断就好了。
然后正解怎么做呢?
我们令ans[i]是异或i之后的1的个数是多少,那么ans[i] = sigma(cnt[i]*num[i^j),cnt[i]表示列那个二进制为i的个数,num[i]表示二进制为i这个数的1的数量是多少。
这个很显然发现 i(ij) = i,这就是一个异或卷积的形式,用FWT加速计算就好了。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = (1<<20)+6;
int n,m,cnt[maxn];
long long x1[maxn],x2[maxn],ans[maxn];
string s[maxn];
long long t[maxn];
void utfxor(long long a[], int n) {
if(n == 1) return;
int x = n >> 1;
for(int i = 0; i < x; ++ i) {
t[i] = (a[i] + a[i + x]) >> 1;
t[i + x] = (a[i + x] - a[i]) >> 1;
}
memcpy(a, t, n * sizeof(long long));
utfxor(a, x); utfxor(a + x, x);
}
long long tmp[maxn];
void tfxor(long long a[], int n) {
if(n == 1) return;
int x = n >> 1;
tfxor(a, x); tfxor(a + x, x);
for(int i = 0; i < x; ++ i) {
tmp[i] = a[i] - a[i + x];
tmp[i + x] = a[i] + a[i + x];
}
memcpy(a, tmp, n * sizeof(long long));
}
void solve(long long a[],long long b[],int n)
{
tfxor(a,n);
tfxor(b,n);
for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i];
utfxor(a,n);
}
int main()
{
for(int i=0;i<maxn;i++){
int tmp = i;
while(tmp){
if(tmp&1)cnt[i]++;
tmp>>=1;
}
}
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
cin>>s[i];
for(int i=0;i<m;i++){
int tmp = 0;
for(int j=0;j<n;j++){
if(s[j][i]=='1')tmp+=1<<j;
}
x1[tmp]++;
}
for(int i=0;i<(1<<n);i++)
x2[i]=min(cnt[i],n-cnt[i]);
solve(x1,x2,1<<n);
long long ans = 1e15;
for(int i=0;i<(1<<n);i++)
ans=min(ans,x1[i]);
cout<<ans<<endl;
}
CROC 2016 - Final Round [Private, For Onsite Finalists Only] C. Binary Table FWT的更多相关文章
- CROC 2016 - Elimination Round (Rated Unofficial Edition) D. Robot Rapping Results Report 二分+拓扑排序
D. Robot Rapping Results Report 题目连接: http://www.codeforces.com/contest/655/problem/D Description Wh ...
- 8VC Venture Cup 2016 - Final Round (Div. 2 Edition)
暴力 A - Orchestra import java.io.*; import java.util.*; public class Main { public static void main(S ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) D. Robot Rapping Results Report 拓扑排序+二分
题目链接: http://www.codeforces.com/contest/655/problem/D 题意: 题目是要求前k个场次就能确定唯一的拓扑序,求满足条件的最小k. 题解: 二分k的取值 ...
- CF #CROC 2016 - Elimination Round D. Robot Rapping Results Report 二分+拓扑排序
题目链接:http://codeforces.com/contest/655/problem/D 大意是给若干对偏序,问最少需要前多少对关系,可以确定所有的大小关系. 解法是二分答案,利用拓扑排序看是 ...
- 8VC Venture Cup 2016 - Final Round (Div. 1 Edition) E - Preorder Test 树形dp
E - Preorder Test 思路:想到二分答案了之后就不难啦, 对于每个答案用树形dp取check, 如果二分的值是val, dp[ i ]表示 i 这棵子树答案不低于val的可以访问的 最多 ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) F - Cowslip Collections 数论 + 容斥
F - Cowslip Collections http://codeforces.com/blog/entry/43868 这个题解讲的很好... #include<bits/stdc++.h ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) E - Intellectual Inquiry dp
E - Intellectual Inquiry 思路:我自己YY了一个算本质不同子序列的方法, 发现和网上都不一样. 我们从每个点出发向其后面第一个a, b, c, d ...连一条边,那么总的不同 ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) E. Intellectual Inquiry 贪心 构造 dp
E. Intellectual Inquiry 题目连接: http://www.codeforces.com/contest/655/problem/E Description After gett ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) C. Enduring Exodus 二分
C. Enduring Exodus 题目连接: http://www.codeforces.com/contest/655/problem/C Description In an attempt t ...
随机推荐
- 两个不等式(Nopier)
- JavaScript-indexOf函数
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- Java将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
java.io 类 BufferedWriter java.lang.Object java.io.Writer java.io.BufferedWriter BufferedWriter publi ...
- canvas放射性渐变填充
今天在学习canvas时,遇到canvas的fillstyle有一个createRadialGradient()方法,创建放射性渐变. 上代码: <!DOCTYPE html> <h ...
- Android--UI
1.layout_width 属性和 layout_height 属性:Android中所有的控件都包含这两个属性,有三种可选值 match_parent, fill_parent, wrap_con ...
- java编程规范
一.规范存在的意义 应用编码规范对于软件本身和软件开发人员而言尤为重要,有以下几个原因: 1.好的编码规范可以尽可能的减少一个软件的维护成本 , 并且几乎没有任何一个软件,在其整个生命周期中,均由最初 ...
- 【转载】php中iconv函数使用方法
原文:http://www.phpweblog.net/star65225692/archive/2011/03/23/7524.html 在选择用什么工具开发,唯一的指导标准就是:用最少的人 ...
- node-webkit教程(14)禁用缓存
1.在开发者工具中禁用缓存 上面这张图,是在node-webkit 中 在开发工具中配置禁用缓存的选项. 使用这个选项可以有效的禁用所有页面缓存. 2. 在配置文件中,配置webkit 缓存禁用和启用 ...
- SQL Server转发记录指针的坏味道
什么是转发记录指针? 转发记录指针是堆表中特有的数据存储机制. 当你修改了某个数据页中的一行时,如果该行所在的数据页已经无法存放其修改后的行, SQL Server会把这行数据移动到一个新的数据页上面 ...
- python __del__
python __del__ 转自:http://blog.csdn.net/bbdxf/article/details/25774763 最近学习<Python参考手册>学到Class部 ...