uoj425

题意

\(q\) 个长度为 \(n\) 的带 \(?\)\(01\)\(T\)
求有多少长度为 \(n\)\(01\) 串存在 \(T\) 中至少一个串能匹配。\(?\ =\ 0\ or\ 1\)

做法1

meet-in-middle 考虑如何合并
暴力做法先搜一半,对 \(T\) 中每个串记录一个 \(2^{\frac{n}{2}}\) 的 bitset 看哪些串匹配。搜另一半的时候将 \(T\) 中匹配的串的 bitset 或起来求个 count。
可以将 \(T\) 分成 \(B\) 块,搜好一半时对块内的 \(2^B\) 个子集算下至少匹配这些串的 bitset。搜另一半时只用或 \(\frac{q}{B}\) 个 bitset。

时间复杂度 \(O(\frac{2^nq}{wB})\)

代码

#include <bits/stdc++.h>

#ifdef __WIN32
#define LLFORMAT "I64"
#else
#define LLFORMAT "ll"
#endif

using namespace std;

const int B = 10, S = 1 << 15, N = 100;

bitset<S> pool[N / B][1 << B];

int main() {
	ios::sync_with_stdio(false);
	vector<int> pw2(B);
	for (int i = 0; i < B; ++i) pw2[i] = 1 << i;
	int n, q;
	cin >> n >> q;
	vector<string> s(q);
	vector<int> bel(q), id(q);
	for (int i = 0; i < q; ++i) cin >> s[i], bel[i] = i / B, id[i] = ((i == 0 || bel[i] != bel[i - 1]) ? 0 : id[i - 1] + 1); 
	string str(n, '?');
	int m = n >> 1;
	function<void(int)> dfs1 = [&](int i) {
		static int x = 0;
		if(i == n) {
			for (int j = 0; j < q; ++j) {
				bool flag = true;
				for (int i = m; i < n; ++i) if((s[j][i] != '?') && (s[j][i] != str[i])) { flag = false; break; }
				if(flag) pool[bel[j]][pw2[id[j]]].set(x);
			}
			++x;
			return;
		}
		str[i] = '0';
		dfs1(i + 1);
		str[i] = '1';
		dfs1(i + 1);
		return;
	};
	dfs1(m);
	for (int i = 0; i <= bel.back(); ++i) {
		static int S = 1 << B;
		for (int s = 1, t; t = s & (-s), s < S; ++s) pool[i][s] = pool[i][t] | pool[i][s ^ t];
	}
	int ans = 0;
	function<void(int)> dfs2 = [&](int i) {
		static bitset<S> all;
		if(i == m) {
			all.reset();
			for (int S = 0, j = 0; j < q; ++j) {
				bool flag = true;
				for (int i = 0; i < m; ++i) if((s[j][i] != '?') && (s[j][i] != str[i])) { flag = false; break; }
				if(flag) S |= pw2[id[j]];
				if(j == q - 1 || bel[j + 1] != bel[j]) all |= pool[bel[j]][S], S = 0;
			}
			ans += all.count();
			return;
		}
		str[i] = '0';
		dfs2(i + 1);
		str[i] = '1';
		dfs2(i + 1);
		return;
	};
	dfs2(0);
	cout << ans << endl;
	return 0;
}
posted @ 2019-01-13 20:55  King_George  阅读(228)  评论(0编辑  收藏  举报