Binary Table CodeForces - 662C (FWT)
Posted uid001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Binary Table CodeForces - 662C (FWT)相关的知识,希望对你有一定的参考价值。
大意: 给定$nm$大小的$01$矩阵, $1\le n\le 20,1\le m\le 1e5$, 可以任选行列翻转, 求最终$1$总数最少为多少.
显然有$O(m2^n)$的暴力算法
也就是枚举翻转哪些行, 然后对于一列, 若$1$的个数多于$0$的个数就翻转.
可以发现对于相同的列, 翻转行对它的影响是相同的.
用$a_i$记录状态为$i$的列的个数, $b_i$记录状态为$i$的列的贡献.
假设翻转行状态为$S$时答案为$f_S$, 枚举每种状态的列的贡献, 就有
$$f_S=\sum\limits_i a_i \oplus Sb_i$$
明显的$xor$卷积形式, 可以用$FWT$求出.
#include <iostream> #include <cstdio> #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; typedef long long ll; const int N = 1e5+10, M = (1<<20)+10; int n, m; ll a[M], b[M]; char s[22][N]; void FWT(ll *a, int n, int tp) for (int i=0; (1<<i)<n; ++i) REP(j,0,n-1) if (j>>i&1) ll l = a[j^1<<i], r = a[j]; a[j^1<<i] += r; a[j] = l-r; if (tp==-1) REP(i,0,n-1) a[i]/=n; void mul(ll *a, ll *b, int n) FWT(a,n,1),FWT(b,n,1); REP(i,0,n-1) a[i]*=b[i]; FWT(a,n,-1); int main() scanf("%d%d", &n, &m); REP(i,1,n) scanf("%s",s[i]+1); REP(i,1,m) int x = 0; REP(j,1,n) (x<<=1)|=s[j][i]==‘1‘; ++a[x]; REP(i,0,(1<<n)-1) int t = __builtin_popcount(i); b[i] = min(t, n-t); mul(a,b,1<<n); ll ans = a[0]; REP(i,1,(1<<n)-1) ans = min(ans, a[i]); printf("%lld\n", ans);
以上是关于Binary Table CodeForces - 662C (FWT)的主要内容,如果未能解决你的问题,请参考以下文章
Binary Table CodeForces - 662C (FWT)
Codeforces 662C Binary Table(快速沃尔什变换)
Codeforces622 C. Binary Table(状压+fwt_xor)
CodeForces - 1003B Binary String Constructing