Binary Table(Codeforces 663E)

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/85213886

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} 种,行翻转相当于对每一列的01状态异或一下,根据异或的a^b=c有 a^c=b,那么可以将行反转后的01串价值设为C , A[i]存储i状态的行的数量, ( A C ) [ i ] = i (A \circ C)[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));
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/85213886