Submission #841099

#TimeUsernameProblemLanguageResultExecution timeMemory
841099peijarAmusement Park (CEOI19_amusementpark)C++17
42 / 100
3027 ms228760 KiB
#include <bits/stdc++.h> #define int long long using namespace std; string to_string(string s) { return s; } template <typename T> string to_string(T v) { bool first = true; string res = "["; for (const auto &x : v) { if (!first) res += ", "; first = false; res += to_string(x); } res += "]"; return res; } void dbg_out() { cout << endl; } template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cout << ' ' << to_string(H); dbg_out(T...); } #ifdef DEBUG #define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__) #else #define dbg(...) #endif template <const int32_t MOD> struct ModInt { int32_t x; ModInt() : x(0) {} ModInt(long long u) : x(u % MOD) { if (x < 0) x += MOD; } friend bool operator==(const ModInt &a, const ModInt &b) { return a.x == b.x; } friend bool operator!=(const ModInt &a, const ModInt &b) { return a.x != b.x; } friend bool operator<(const ModInt &a, const ModInt &b) { return a.x < b.x; } friend bool operator>(const ModInt &a, const ModInt &b) { return a.x > b.x; } friend bool operator<=(const ModInt &a, const ModInt &b) { return a.x <= b.x; } friend bool operator>=(const ModInt &a, const ModInt &b) { return a.x >= b.x; } static ModInt sign(long long k) { return ((k & 1) ? ModInt(MOD - 1) : ModInt(1)); } ModInt &operator+=(const ModInt &m) { x += m.x; if (x >= MOD) x -= MOD; return *this; } ModInt &operator-=(const ModInt &m) { x -= m.x; if (x < 0LL) x += MOD; return *this; } ModInt &operator*=(const ModInt &m) { x = (1LL * x * m.x) % MOD; return *this; } friend ModInt operator-(const ModInt &a) { ModInt res(a); if (res.x) res.x = MOD - res.x; return res; } friend ModInt operator+(const ModInt &a, const ModInt &b) { return ModInt(a) += ModInt(b); } friend ModInt operator-(const ModInt &a, const ModInt &b) { return ModInt(a) -= ModInt(b); } friend ModInt operator*(const ModInt &a, const ModInt &b) { return ModInt(a) *= ModInt(b); } static long long fp(long long u, long long k) { long long res = 1LL; while (k > 0LL) { if (k & 1LL) res = (res * u) % MOD; u = (u * u) % MOD; k /= 2LL; } return res; } static constexpr int mod() { return MOD; } ModInt fastpow(long long k) { return ModInt(fp(x, k)); } ModInt inv() { assert(x); return ModInt(fp(x, MOD - 2)); } ModInt &operator/=(const ModInt &m) { return *this *= ModInt(m).inv(); } friend ModInt operator/(const ModInt &a, const ModInt &b) { return ModInt(a) *= ModInt(b).inv(); } friend ostream &operator<<(ostream &out, const ModInt &a) { return out << a.x; } friend istream &operator>>(istream &in, ModInt &a) { return in >> a.x; } friend string to_string(ModInt u) { return to_string(u.x); } }; // const int MOD = 1e9 + 7; const int MOD = 998244353; using Mint = ModInt<MOD>; signed main(void) { ios_base::sync_with_stdio(false); cin.tie(0); int n, m; cin >> n >> m; vector<int> adj(n); vector<int> bitAdj(n); for (int i = 0; i < m; ++i) { int u, v; cin >> u >> v; --u, --v; adj[u] |= 1 << v; bitAdj[u] |= 1 << v; bitAdj[v] |= 1 << u; } vector<int> areBad(n); for (int u = 0; u < n; ++u) for (int v = 0; v < u; ++v) if (!((1 << v) & bitAdj[u])) areBad[u] |= 1 << v; vector<vector<int>> inComplement(1 << n); for (int msk = 0; msk < (1 << n); ++msk) { int c = (1 << n) - 1 - msk; int complement = c; while (true) { inComplement[msk].push_back(c); if (!c) break; c = (c - 1) & complement; } sort(inComplement[msk].begin(), inComplement[msk].end()); } auto getId = [&](int msk, int c) { return lower_bound(inComplement[msk].begin(), inComplement[msk].end(), c) - inComplement[msk].begin(); }; vector<vector<Mint>> dpBack(1 << n); vector<vector<Mint>> dpForward(1 << n); for (int msk = 0; msk < (1 << n); ++msk) { dpBack[msk].resize(inComplement[msk].size()); dpForward[msk].resize(inComplement[msk].size()); } dpBack[0][0] = 1; for (int added = 0; added < (1 << n); ++added) { int complement = (1 << n) - 1 - added; for (int i = 0; i < (int)inComplement[added].size(); ++i) { int bad = inComplement[added][i]; for (int nxt = 0; nxt < n; ++nxt) if (!((1 << nxt) & added) and !((1 << nxt) & bad)) { int nxtBad = bad & (bad ^ bitAdj[nxt]); nxtBad |= areBad[nxt] & complement; int j = getId(added ^ (1 << nxt), nxtBad); dpBack[added ^ (1 << nxt)][j] += dpBack[added][i]; } } } dpForward[(1 << n) - 1][0] = 1; for (int added = (1 << n) - 2; added >= 0; --added) { for (int i = 0; i < (int)inComplement[added].size(); ++i) { int bad = inComplement[added][i]; for (int nxt = 0; nxt < n; ++nxt) if (!((1 << nxt) & added) and !((1 << nxt) & bad)) { int nxtBad = bad & (bad ^ bitAdj[nxt]); nxtBad |= areBad[nxt] & inComplement[added].back(); dpForward[added][i] += dpForward[added ^ (1 << nxt)][getId(added ^ (1 << nxt), nxtBad)]; } } } Mint sol = 0; for (int added = 0; added < (1 << n); ++added) { int complement = (1 << n) - 1 - added; for (int i = 0; i < (int)inComplement[added].size(); ++i) { int bad = inComplement[added][i]; for (int nxt = 0; nxt < n; ++nxt) if (!((1 << nxt) & added) and !((1 << nxt) & bad)) { int nxtBad = bad & (bad ^ bitAdj[nxt]); nxtBad |= areBad[nxt] & complement; Mint cnt = dpForward[added ^ (1 << nxt)][getId(added ^ (1 << nxt), nxtBad)] * dpBack[added][i]; int cntFlip = __builtin_popcount(adj[nxt] & added); sol += cnt * cntFlip; } } } cout << sol << endl; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...