Loading

【题解】CF1326F2 Wise Men (Hard Version)

值得一做的数数题(容斥原理,状压DP,子集卷积)

我们要求准确的生成串为 \(s\) 的方案并不好做,考虑转换为求高维前缀和,然后用容斥还原。

这样 \(s_i=1\) 表示必须有边,\(s_i=0\) 表示无限制。

对于任何一个串 \(s\),我们将必须有的边连起来,会得到若干个单链,现在我们要求用若干个大小固定的单链覆盖 \(n\) 个点,不重不漏。

状压 DP 求出 \(f_{s,x}\) 表示以 \(x\) 结尾,经过点集为 \(s\) 的链数,进一步求出 \(g_{s}\) 表示点集为 \(s\) 的链数。

不难发现不重不漏的方案数,本质上就是 \(g\) 数组的子集卷积。

一个串 \(s\) 对应一个链长度的划分方案,我们先对每种划分算出方案,存在哈希表里,然后枚举 \(s\) 求出对应划分的贡献。

\(n=18\) 的划分数并不大,直接暴搜处理即可,最后别忘了还原答案。

#define N 18
void fwt_or(LL *u, int n){
	for(int l = 2, k = 1; l <= n; l <<= 1, k <<= 1)
		for(int i = 0; i < n; i += l)rep(j, 0, k - 1)
			u[i + j + k] += u[i + j];
}
void ifwt_and(LL *u,int n){
	for(int l = 2, k = 1; l <= n; l <<= 1, k <<= 1)
		for(int i = 0; i < n; i += l)rep(j, 0, k - 1)
			u[i + j] -= u[i + j + k];
}
int n, w, d[N][N], bt[1 << N]; LL g[N][1 << N], c[N][1 << N], ans[1 << N], f[N][1 << N];
char ch[N + 5];
unordered_map<int, LL> h;
void dfs(int res,int mn,int cur,int p){
	if(!res){
		LL sum = 0;
		rep(i, 0, w)
			(bt[w ^ i] & 1) ? sum -= c[cur - 1][i] : sum += c[cur - 1][i];
		h[p] = sum;
	}
	else{
		rep(s, mn, res){
			rep(i, 0, w)c[cur][i] =  c[cur - 1][i] * g[s - 1][i];
			dfs(res - s, s, cur + 1, (p * 1LL * bas + s) % P);
		}
	}
}
int main() {
	read(n);
	rep(i, 0, n - 1){
		scanf("%s", ch);
		rep(j, 0, n - 1)d[i][j] = ch[j] - '0';
		f[i][1 << i] = 1;
	}
	w = (1 << n) - 1;
	rp(s, w){
		bt[s] = bt[s >> 1] + (1 & s);
		if(bt[s] > 1){
			rep(i, 0, n - 1)if(1 & (s >> i)){
				rep(j, 0, n - 1)if(i != j && (1 & (s >> j)) && d[j][i])
					f[i][s] += f[j][s ^ (1 << i)];
				g[bt[s] - 1][s] += f[i][s];
			}
		}else g[0][s]++;
	}
	rep(i, 0, n - 1)fwt_or(g[i], 1 << n);
	rep(i, 0, w)c[0][i] = 1;
	dfs(n, 1, 1, 0);
	rep(i, 0, w >> 1){
		vector<int>u; int res = 1, cur = 0;
		rep(j, 0, n - 2)if(1 & (i >> j))res++; else u.pb(res), res = 1;
		u.pb(res); sort(u.begin(), u.end());
		go(x, u)cur = (cur * 1LL * bas + x) % P;
		ans[i] = h[cur];
	}
	ifwt_and(ans, 1 << (n - 1));
	rep(i, 0, w >> 1)printf("%lld ", ans[i]); el;
	return 0;
}
posted @ 2022-02-09 15:28  7KByte  阅读(72)  评论(0编辑  收藏  举报