633E Binary Table
分析
我们发现n特别小,所以可以从这里入手
我们记录出所有列中某一种状态的列有多少个
我们再记录出每种列最少有多少个1(原来的1的个数和取反后的个数去最小值)
于是我们可以得出对于所有列异或一个数的答案
(实际就是对于每一行有一个全异或1或不异或的操作,将所有行压起来)
于是我们不难得到式子$Ans_i = \sum a_j * b_{j^i}$
直接fwt即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
string s[25];
int a[2000000],b[2000000],n,m,N;
inline void fwt(int a[],int f){
int i,j,k;
for(i=1;i<N;i<<=1)
for(j=0;j<N;j+=(i<<1))
for(k=0;k<i;k++){
int x=a[j+k],y=a[i+j+k];
a[j+k]=x+y,a[i+j+k]=x-y;
if(f==-1)a[j+k]/=2,a[i+j+k]/=2;
}
}
signed main(){
int i,j,k;
scanf("%lld%lld",&n,&m);
N=(1<<n);
for(i=1;i<=n;i++)cin>>s[i];
for(i=0;i<m;i++){
k=0;
for(j=1;j<=n;j++)k=(k<<1)+(s[j][i]-'0');
a[k]++;
}
for(i=1;i<N;i++)b[i]=b[i>>1]+(i&1);
for(i=0;i<N;i++)b[i]=min(b[i],n-b[i]);
fwt(a,1),fwt(b,1);
for(i=0;i<N;i++)a[i]=a[i]*b[i];
fwt(a,-1);
int Ans=1e9+7;
for(i=0;i<N;i++)Ans=min(Ans,a[i]);
cout<<Ans;
return 0;
}