题解 CF1326F2 【Wise Men (Hard Version)】
AutumnKite · · 题解
宣传 blog(Github Pages 上不去可以用 Gitee 上的镜像)
题目传送门
题解
发现既有有边又有没边的限制非常难搞,于是我们考虑容斥,即计算
计算出
考虑如何计算
可以发现,对于任意
对于一个划分
那么我们先考虑选
那么对于一个划分
其中
注意到由于
存在第一个条件时,我们只要将
直接将所有
总时间复杂度
实现得不好可能会变成
代码
int n;
std::vector<int> bitcnt;
std::vector<std::vector<long long>> f;
std::vector<std::vector<long long>> g;
std::map<std::vector<int>, std::vector<int>> part;
std::vector<long long> ans;
void dfs(int r, const std::vector<int> &l, const std::vector<long long> &s){
if (!r){
long long res = 0;
int mask = (1 << n) - 1;
for (register int i = 0; i < (1 << n); ++i)
if (bitcnt[mask ^ i] & 1) res -= s[i]; else res += s[i];
const std::vector<int> &p = part[l];
for (int v : p) ans[v] += res;
return;
}
int lst = l.empty() ? 1 : l.back();
for (register int k = lst; k <= r; ++k){
if (k < r && r - k < k) continue;
std::vector<int> nl(l);
std::vector<long long> ns(s);
nl.push_back(k);
for (register int i = 0; i < (1 << n); ++i) ns[i] *= g[k - 1][i];
dfs(r - k, nl, ns);
}
}
void solve(){
read(n);
std::vector<std::vector<int>> E(n);
for (register int i = 0; i < n; ++i)
for (register int j = 0; j < n; ++j){
char ch;
while (!isdigit(ch = getchar())) ;
if (ch == '1') E[i].push_back(j);
}
bitcnt.resize(1 << n);
bitcnt[0] = 0;
for (register int i = 1; i < (1 << n); ++i) bitcnt[i] = bitcnt[i >> 1] + (i & 1);
f.resize(n, std::vector<long long>(1 << n, 0));
g.resize(n, std::vector<long long>(1 << n, 0));
for (register int i = 0; i < n; ++i) f[i][1 << i] = 1;
for (register int S = 1; S < (1 << n); ++S)
for (register int i = 0; i < n; ++i)
if (f[i][S]){
g[bitcnt[S] - 1][S] += f[i][S];
for (int v : E[i]) if (!(S >> v & 1)) f[v][S | (1 << v)] += f[i][S];
}
for (register int k = 0; k < n; ++k)
for (register int i = 0; i < n; ++i)
for (register int S = 0; S < (1 << n); ++S)
if (S >> i & 1) g[k][S] += g[k][S ^ (1 << i)];
for (register int S = 0; S < (1 << (n - 1)); ++S){
std::vector<int> p;
int x = 1;
for (register int i = 0; i < n - 1; ++i)
if (S >> i & 1) ++x; else p.push_back(x), x = 1;
p.push_back(x);
std::sort(p.begin(), p.end());
part[p].push_back(S);
}
ans.resize(1 << (n - 1), 0);
dfs(n, std::vector<int>(), std::vector<long long>(1 << n, 1));
for (register int i = 0; i < n - 1; ++i)
for (register int S = 0; S < (1 << (n - 1)); ++S)
if (S >> i & 1) ans[S ^ (1 << i)] -= ans[S];
for (long long v : ans) print(v, ' ');
putchar('\n');
}