Binary Table(Codeforces 663E)

92 篇文章 0 订阅
86 篇文章 0 订阅

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?

FWT是来优化卷积的,那么要找不定量,发现行翻转只有 2 20 2^{20} 220种,行翻转相当于对每一列的01状态异或一下,根据异或的a^b=c有 a^c=b,那么可以将行反转后的01串价值设为C , A[i]存储i状态的行的数量, ( A ∘ C ) [ i ] = 行 翻 转 为 i 时 的 答 案 (A \circ C)[i] = 行翻转为i时的答案 (AC)[i]=i,对于列翻转发现就是取反,那么在C中可以提前处理

#include<bits/stdc++.h>
#define maxn (1<<20)
#define LL long long
using namespace std;

int n,m,len;
LL bt[maxn],ct[maxn],f[maxn];
char ch[maxn];

int main()
{
	scanf("%d%d",&n,&m);
	len = 1<<n;
	for(int i=0;i<n;i++)
	{
		scanf("%s",ch);
		for(int j=0;j<m;j++)
			f[j] =( (f[j] << 1) + (ch[j] == '1'));
	}
	for(int i=0;i<m;i++) ct[f[i]] ++;
	for(int i=1;i<len;i++) bt[i] = bt[i>>1] + (i&1);
	for(int i=0;i<len;i++) bt[i] = min(bt[i] , bt[i ^ (len-1)]);
	
	for(int L=2;L<=len;L<<=1)
		for(int st=0,l=L>>1;st<len;st+=L)
			for(int k=0;k<l;k++)
			{
				LL tmp = bt[st+k];
				bt[st+k] = tmp + bt[st+k+l];
				bt[st+k+l] = tmp - bt[st+k+l];
				
				tmp = ct[st+k];
				ct[st+k] = tmp + ct[st+k+l];
				ct[st+k+l] = tmp - ct[st+k+l];
			}
	
	for(int i=0;i<len;i++) 
		ct[i] = ct[i] * bt[i];
	
	for(int L=2;L<=len;L<<=1)
		for(int st=0,l=L>>1;st<len;st+=L)
			for(int k=0;k<l;k++)
			{
				LL tmp = ct[st+k];
				ct[st+k] = (tmp + ct[st+k+l]) / 2;
				ct[st+k+l] = (tmp - ct[st+k+l]) / 2;
			}
	
	printf("%I64d\n",*min_element(ct,ct+len));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值