专栏文章
题解:AT_abc396_g [ABC396G] Flip Row or Col
AT_abc396_g题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipxkuzs
- 此快照首次捕获于
- 2025/12/03 19:35 3 个月前
- 此快照最后确认于
- 2025/12/03 19:35 3 个月前
提供一个 FWT 做法。
首先,我们看到输入的 十分小,于是考虑 枚举每一列是否翻转的状态,记为 。对于第 行,将这一行的数改为用二进制表示,记为 。
我们设 表示 在二进制下 的个数, 表示异或运算,那么说如果 ,就说明这一行全部异或一产生的贡献会更小,于是选择异或一。
设 表示当每一列是否翻转的状态为 时矩阵中一的个数最少是多少,那么容易得出:
现在我们考虑如何快速求出所有 。
设 ,。
于是我们考虑化繁一下式子:
然后就可以用 FWT 快速求解了。
code
CPP#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;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...