对每一列状压。
令
ai
表示状态
i
的出现次数,
然后考虑行操作。假设行操作的状态为
∑i=02n−1ai×bi⊕S
直接FWT就好了。
#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define ll long long
ll a[2000001],b[2000001],Ans;
int i,j,k,n,m,p[30],x;
char s[N];
bool f[21][N];
inline void FWT(ll* a,int n,int d){
for(int i=1;i<n;i<<=1)
for(int j=0;j<n;j+=(i<<1))
for(int k=0;k<i;k++){
ll x=a[j+k],y=a[j+k+i];
a[j+k]=x+y;a[j+k+i]=x-y;
if(d==-1){
a[j+k]/=2;a[j+k+i]/=2;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%s",s);
for(j=0;j<m;j++)f[i][j+1]=s[j]-'0';
}
for(p[0]=i=1;i<=20;i++)p[i]=p[i-1]<<1;
for(i=1;i<=m;i++){
x=0;
for(j=1;j<=n;j++)x+=p[j-1]*f[j][i];
a[x]++;
}
for(i=0;i<p[n];i++){
for(j=0;j<n;j++)
if((i&p[j])>0)b[i]++;
b[i]=min(b[i],n-b[i]);
}
FWT(a,p[n],1);FWT(b,p[n],1);
for(i=0;i<p[n];i++)a[i]*=b[i];
FWT(a,p[n],-1);
Ans=1ll*n*m;
for(i=0;i<p[n];i++)Ans=min(Ans,a[i]);
cout<<Ans<<endl;
return 0;
}