分析
据说本来这题吉老师打算出给zjoi的 233
代码
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x)
{
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar())
{
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar())
{
x = x * 10 + c - '0';
}
if (f)
{
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b)
{
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b)
{
return a > b ? a = b, true : false;
}
const int N = 30;
const int M = 5000005;
const int mod = 998244353;
int n, m, tim, tot, adj[N], inp[N], inv[N], vis[N], c[N][N];
unordered_map <int, int> idx;
vector <int> ply[M];
inline int DFS(int x, int s)
{
int ret = 1 << x;
vis[x] = tim;
for (int i = 0; i < n; ++i) {
if (((s & adj[x]) >> i & 1) && vis[i] != tim)
{
ret |= DFS(i, s);
}
}
return ret;
}
inline void Add(vector <int> &a, vector <int> b)
{
for (; a.size() < b.size(); a.pb(0));
for (int i = 0; i < b.size(); ++i)
{
a[i] = (a[i] + b[i]) % mod;
}
}
inline vector <int> Mul(vector <int> a, vector <int> b)
{
vector <int> c(a.size() + b.size() - 1, 0);
for (int i = 0; i < a.size(); ++i)
{
for (int j = 0; j < b.size(); ++j)
{
c[i + j] = (1LL * a[i] * b[j] + c[i + j]) % mod;
}
}
return c;
}
inline vector <int> Int(vector <int> a)
{
vector <int> b(a.size() + 1, 0);
for (int i = 0; i < a.size(); ++i)
{
b[i + 1] = 1LL * a[i] * inv[i + 1] % mod;
}
return b;
}
inline void Update(vector <int> &a, vector <int> b, int d)
{
vector <int> e = Int(Mul(b, vector <int> (c[d], c[d] + d + 1)));
Add(a, e);
for (int i = 1; i < e.size(); ++i)
{
a[0] = (a[0] - 1LL * e[i] * inp[i] % mod + mod) % mod;
}
}
inline int Solve(int s)
{
if (idx[s])
{
return idx[s];
}
if (!s)
{
ply[++tot] = {1};
return tot;
}
int x = idx[s] = ++tot, y = __builtin_popcount(s);
vector <int> com;
++tim;
for (int i = 0; i < n; ++i)
{
if ((s >> i & 1) && vis[i] != tim)
{
com.pb(DFS(i, s));
}
}
if (com.size() > 1)
{
ply[x] = {1};
for (int i = 0; i < com.size(); ++i)
{
ply[x] = Mul(ply[x], ply[Solve(com[i])]);
}
return x;
}
ply[x].resize(y + 1), ply[x][0] = inp[y];
for (int i = 0; i < n; ++i)
{
if (s >> i & 1)
{
Update(ply[x], ply[Solve((s ^ adj[i]) & s)], __builtin_popcount(s & adj[i]) - 1);
}
}
return x;
}
int main()
{
Read(n), Read(m), inv[0] = inv[1] = inp[0] = 1, inp[1] = mod + 1 >> 1;
for (int i = 2; i <= n + 1; ++i)
{
inp[i] = 1LL * inp[i - 1] * inp[1] % mod;
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
}
for (int i = 0; i <= n; ++i)
{
c[i][0] = 1;
for (int j = 1; j <= i; ++j)
{
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
}
for (int i = 0; i <= n; ++i)
{
for (int j = 0; j <= i; ++j)
{
if (j & 1)
{
c[i][j] = (mod - c[i][j]) % mod;
}
}
}
for (int i = 1, x, y; i <= m; ++i)
{
Read(x), Read(y), --x, --y;
adj[x] |= 1 << y, adj[y] |= 1 << x;
}
for (int i = 0; i < n; ++i)
{
adj[i] |= 1 << i;
}
vector <int> ans = ply[Solve((1 << n) - 1)];
int ret = 0;
for (int i = 0; i <= n; ++i)
{
ret = (1LL * ans[i] * inv[n + 1] + ret) % mod;
ret = (1LL * ans[i] * inv[n - i + 1] % mod * ((1 << n - i + 1) - 1) + ret) % mod;
}
printf("%d\n", (mod + 2 - ret) % mod);
}