题解:AT_abc396_g [ABC396G] Flip Row or Col
提供一个 FWT 做法。
首先,我们看到输入的
我们设
设
现在我们考虑如何快速求出所有
设
于是我们考虑化繁一下式子:
然后就可以用 FWT 快速求解了。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=(1<<18)+10;
int m,n;
ll A[N],B[N];
ll a[N],b[N];
void xorr(ll*f,double type)
{
for(int len=2;len<=n;len<<=1)
{
int mid=len>>1;
for(int i=0;i<n;i+=len)
{
for(int j=0;j<mid;j++)
{
f[i+j]+=f[i+j+mid];
f[i+j+mid]=f[i+j]-2*f[i+j+mid];
f[i+j]=f[i+j]*type,f[i+j+mid]=f[i+j+mid]*type;
}
}
}
}
int we;
string s;
#define popcount(x) __builtin_popcount(x)
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>we>>m,n=1<<m;
for(int i=1;i<=we;i++){
cin>>s;
int sum=0;
for(int i=0;i<m;i++) sum=sum+((s[i]-'0')<<i);
a[sum]++;
}
for(int i=0;i<n;i++) b[i]=min(popcount(i),popcount(n-1-i));
xorr(a,1),xorr(b,1);
for(int i=0;i<n;i++) a[i]=a[i]*b[i];
xorr(a,0.5);
ll ans=1e18;
for(int i=0;i<n;i++) ans=min(ans,a[i]);
cout<<ans<<"\n";
return 0;
}