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 ...
随机推荐
- BestCoder Round #87 1001
GCD is Funny Accepts: 524 Submissions: 1147 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 655 ...
- Jplayer歌词同步显示插件
http://blog.csdn.net/wk313753744/article/details/38758317 1.该插件是一个jquery的编写的跟jplayer实现歌词同步的插件,最终效果如图 ...
- 用scala实现一个sql执行引擎-(下)
执行 上一篇讲述了如何通过scala提供的内置DSL支持,实现一个可以解析sql的解析器,这篇讲如何拿到了解析结果-AST以后,如何在数据上进行操作,得到我们想要的结果.之前说到,为什么选择scala ...
- C++网络编程 Java网络编程
C++ MFC C++ STL C++ 模板 C++ DLL C++ OpenGL C++ OSG C++ GIS (GRASS QGIS POSTGRE GDAL/OGR) ____________ ...
- 如何评估ETL的数据加载时间
简述如何评估大型ETL数据加载时间. 答:评估一个大型的ETL的数据加载时间是一件很复杂的事情.数据加载分为两类,一类是初次加载,另一类是增量加载. 在数据仓库正式投入使用时,需要进行一次初次加载,而 ...
- selenium通过WebDriverWait实现ajax测试,实现等页面元素加载完成
WebDriverWait(driver, 10)10秒内每隔500毫秒扫描1次页面变化,当出现指定的元素后结束. http://fox1984.iteye.com/blog/1225265new W ...
- 如何使不同主机上的docker容器互相通信
docker启动时,会在宿主主机上创建一个名为docker0的虚拟网络接口,默认选择172.17.42.1/16,一个16位的子网掩码给容器提供了65534个IP地址.docker0只是一个在绑定到这 ...
- SQL语句汇总(二)——数据修改、数据查询
首先创建一张表如下,创建表的方法在上篇介绍过了,这里就不再赘述. 添加新数据: INSERT INTO <表名> (<列名列表>) VALUES (<值列表>) ...
- IPv6协议
IPv4协议仅能提供约2.5亿个IP地址, 即使使用CIDR和NAT等技术进行扩展也无法满足日益增长的需要. IETF于1996年开始研究下一代IP协议IPv6, 并于1998年12月正式公布(RFC ...
- node-webkit教程(9)native api 之Tray(托盘)
node-webkit教程(9)native api 之Tray(托盘) 文/玄魂 目录 node-webkit教程(9)native api 之Tray(托盘) 前言 9.1 Tray简介 9.2 ...