THUWC2018 随机算法
Posted hfccccccccccccc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了THUWC2018 随机算法相关的知识,希望对你有一定的参考价值。
看了题解
题目大意
略
解法一
独立集那一套东西不是很好处理。为了消除加入一个点对之后点的影响,不妨在向独立集加入一个点时直接顺带加入和它相邻的点,用排列数预计算方案。
解法二
考虑一个集合的最后一个被加入独立集的点是什么。
实现
解法一:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MD = 998244353;
int pow_mod(int x, int n) {
int r = 1;
while (n) {
if (n & 1) r = ll(r) * x % MD;
x = ll(x) * x % MD;
n >>= 1;
}
return r;
}
const int NN = 20;
int g[NN];
int dp[1<<NN], b[1<<NN];
int fac[NN+1], ifac[NN+1], pop[1<<NN];
int n, m;
void precompute() {
fac[0] = ifac[0] = 1;
for (int i = 1; i <= NN; i++) {
fac[i] = ll(i) * fac[i-1] % MD;
ifac[i] = pow_mod(fac[i], MD - 2);
}
for (int i = 1; i < (1 << NN); i++) {
pop[i] = pop[i>>1] + (i & 1);
}
}
int perm(int n, int m) {
if (n < 0 || m < 0 || n < m) return 0;
return ll(fac[n]) * ifac[n-m] % MD;
}
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
cin >> n >> m;
precompute();
for (int i = 0; i < n; i++) g[i] = 1 << i;
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b; a--; b--;
g[a] |= 1 << b;
g[b] |= 1 << a;
}
dp[0] = 1;
const int S = (1 << n) - 1;
for (int t = 0; t <= S; t++) {
if (!dp[t]) continue;
for (int i = 0; i < n; i++) if (!(t & (1 << i))) {
int u = t | g[i];
if (b[t] + 1 > b[u]) {
b[u] = b[t] + 1;
dp[u] = 0;
}
if (b[t] + 1 == b[u]) {
dp[u] += ll(dp[t]) * perm(n-1-pop[t], pop[(t&g[i])^g[i]]-1) % MD;
if (dp[u] >= MD) dp[u] -= MD;
}
}
}
cout << ll(dp[S]) * ifac[n] % MD << ‘
‘;
return 0;
}
解法二:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int NN = 20;
const int MD = 998244353;
int n, m;
int g[NN];
int inv[NN+1];
int dp[1<<NN], ma[1<<NN];
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
cin >> n >> m;
inv[1] = 1;
for (int i = 2; i <= n; i++) {
inv[i] = ll(MD - MD / i) * inv[MD % i] % MD;
}
for (int i = 0; i < n; i++) g[i] = 1 << i;
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b; a--; b--;
g[a] |= 1 << b;
g[b] |= 1 << a;
}
for (int i = 0; i < n; i++) g[i] = ~g[i];
dp[0] = 1;
for (int v = 1; v < (1 << n); v++) {
int pop = 0;
for (int i = 0; i < n; i++) if ((v >> i) & 1) {
int u = (v & g[i]);
if (ma[u] + 1 > ma[v]) {
ma[v] = ma[u] + 1;
dp[v] = 0;
}
if (ma[u] + 1 == ma[v]) {
dp[v] += dp[u];
if (dp[v] >= MD) dp[v] -= MD;
}
pop++;
}
dp[v] = ll(dp[v]) * inv[pop] % MD;
}
cout << dp[(1<<n)-1] << endl;
return 0;
}
以上是关于THUWC2018 随机算法的主要内容,如果未能解决你的问题,请参考以下文章
P4547 [THUWC2017]随机二分图(状压,期望DP)