Description
给定一个
N
*
Data Constraint
Solution
考虑把每一列压成
20
位的二进制数,对行的操作也可以看成一个
20
位的整数,同时显然有,同一行或同一列最多操作一次,操作的先后顺序对矩阵的最终状态不会有影响。
设
ai
表示第
i
列上的二进制数,考虑对行的操作为
上述做法的时间复杂度为
O
(
等价于
Fx=∑ixork=xCk∗Ei
上述卷积形式用 FWT 实现即可。时间复杂度 O (
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
#define min(a,b) ((a)<(b)?(a):b)
using namespace std;
typedef long long ll;
const ll N=4e6;
int a[N],n,m,j,k,l,i,o,p;
ll aa[N],bb[N],cc[N];
int qz(int o)
{
int yy=0;
for(;o;o>>=1)yy+=(o&1);
return min(n-yy,yy);
}
void DWT(long long *a,int n)
{
ll k=0;
for(int m=2;m<=n;m<<=1)
{
int half=m/2;
for(i=0;i<n-1;i+=m)
fo(l,i,i+half-1){
k=a[l+half];
a[l+half]=a[l]-k;
a[l]=a[l]+k;
}
}
}
void UNDWT(long long *a,int n)
{
ll k=0;
for(int m=2;m<=n;m<<=1){
int half=m/2;
for(int i=0;i<n-1;i+=m)
fo(l,i,i+half-1){
k=a[l+half];
a[l+half]=(a[l]-k)/2;
a[l]=(a[l]+k)/2;
}
}
}
void FWT(long long *a,long long *b,long long *c,int len)
{
DWT(a,len); DWT(b,len);
fo(i,0,len-1)c[i]=a[i]*b[i];
UNDWT(c,len);
}
int main()
{
cin>>n>>m;
char k=getchar();
fo(i,1,n){
fo(l,1,m)a[l]=(a[l]<<1)+(getchar()-48);
char k=getchar();
}
fo(i,1,m)++aa[a[i]];
p=1<<n;
fo(i,0,p-1)bb[i]=qz(i);
FWT(aa,bb,cc,p);
ll ans=(ll)m*(ll)m*(ll)n;
fo(i,0,p-1)
ans=min(ans,cc[i]);
printf("%I64d",ans);
}