Binary Table

题意

CF662C
有个 \(n(\leq20)\)\(m(\leq10^5)\) 列的 01 矩阵,每次操作可以翻转一行或一列的颜色,最小化 1 的个数,并输出。

暴力

注意到 \(n\) 很小,可以枚举所有行翻转的选择。

那么对于其中一种情况,只要能算出 \(m\) 列中每一列的最小 1 的个数,相加即是答案。

时间复杂度 \(O(m \times 2^n)\)

肯定 T 飞。

优化

对于一列,它的状态是 \(s\)(1到n行的状态),如果当前选择的行翻转状态为 \(x\), 那么现在的状态就是 \(x \oplus s\)

对于同样的状态,可以记其个数为 \(cnt_s\), 并且可以预处理出状态 \(s\), 最小的 1/0 的个数 \(val_s\)

答案就是:

\[\sum_{x = 0}^{2^n} cnt_s \times val_{s \oplus x} \]

变一下形式:

\[\sum_{x = s \oplus y} cnt_s \times val_y \]

这就是异或卷积的形式。

用 fwt 优化,时间复杂度 \(O(n \times 2^n)\)

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;

using ll = long long;
const int MAXN = 1200010;
const int INF = 1e18;
const int mod = 1000000007;

//#define ll long long
template <typename T>
void Read(T &x) {
	x = 0; T f = 1; char a = getchar();
	for(; a < '0' || '9' < a; a = getchar()) if (a == '-') f = -f;
	for(; '0' <= a && a <= '9'; a = getchar()) x = (x * 10) + (a ^ 48);
	x *= f;
}

int n, m;
int a[21][MAXN], cnt[MAXN], val[MAXN]; 

void fwt(int *f, int n, int op) {
	for (int p = 2; p <= n; p <<= 1) {
		int len = p >> 1;
		for (int k = 0; k < n; k += p)
			for (int i = k; i < k + len; i ++) {
				int left = f[i], right = f[i + len]; 
				f[i] = (left + right);
				f[i + len] = (left - right); 
				if (op == -1) f[i] >>= 1, f[i + len] >>= 1; 
			}
	}
}

char s[MAXN];
signed main() { 
	cin >> n >> m ;
	for (int i = 1; i <= n; i ++) {
		cin >> s + 1; 
		for (int j = 1; j <= m; j ++)
			a[i][j] = s[j] - '0';  
	}
	
	for (int j = 1; j <= m; j ++) {
		int sum = 0; 
		for (int i = 1; i <= n; i ++)
			sum |= (1 << i - 1) * a[i][j]; 
		cnt[sum] ++; 
	}
	
	for (int i = 1; i < (1 << n); i ++) {
		int ct = 0;
		for (int j = i; j; j ^= j & -j) ct ++; 
		val[i] = min(ct, n - ct); 
	}	
	
	fwt(cnt, (1 << n), 1);
	fwt(val, (1 << n), 1);
	for (int i = 0; i < (1 << n); i ++)
		cnt[i] = cnt[i] * val[i];
	fwt(cnt, (1 << n), -1);
	
	int ans = INF; 
	for (int i = 0; i < (1 << n); i ++)
		ans = min(ans, cnt[i]);
	cout << ans; 
 	return 0;
} 
posted @ 2022-02-17 15:01  qjbqjb  阅读(18)  评论(0编辑  收藏  举报