Submission #1222344

#TimeUsernameProblemLanguageResultExecution timeMemory
1222344_callmelucianAmusement Park (CEOI19_amusementpark)C++17
0 / 100
3 ms6472 KiB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using pl = pair<ll,ll>;
using pii = pair<int,int>;
using tpl = tuple<int,int,int>;

#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())

vector<int> adj[18];
vector<pii> dp[1 << 18];
int bitmask[18], good[1 << 18][18];

const int MOD = 998'244'353;
const int inv2 = 499'122'177;

int add (int a, int b) { return a + b - (a + b < MOD ? 0 : MOD); }
int sub (int a, int b) { return a - b + (a - b >= 0 ? 0 : MOD); }
int mul (int a, int b) { return 1LL * a * b % MOD; }

int binpow (int a, int b) {
    int ans = 1;
    for (; b; b >>= 1, a = mul(a, a))
        if (b & 1) ans = mul(ans, a);
    return ans;
}

bool getCur (int mask, int pos) {
    return mask >> pos & 1;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, m; cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int a, b; cin >> a >> b;
        a--, b--;
        adj[a].push_back(b);
        adj[b].push_back(a);
        bitmask[a] |= (1 << b);
        bitmask[b] |= (1 << a);
    }
    for (int i = 0; i < n; i++)
        sort(all(adj[i]), greater<int>());

    /// find valid masks & setup mask case
    for (int mask = 0; mask < (1 << n); mask++) {
        bool valid = 1;
        for (int i = 0; i < n; i++)
            if (getCur(mask, i) && (mask & bitmask[i])) { valid = 0; break; }
        if (valid) dp[0].emplace_back(mask, 1);
    }

    for (int mask = 0; mask < (1 << n); mask++) {
        for (int i = 0; i < n; i++) {
            int cur = 0;
            for (int j : adj[i])
                if (!(mask & bitmask[j])) cur |= (1 << j);
            good[mask][i] = cur;
        }
    }

    /// run DP
    int ans = 0;
    for (int A = 0; A < (1 << n); A++) {
        if (A) {
            sort(all(dp[A]));
            vector<pii> tmp;
            for (auto [B, val] : dp[A]) {
                if (tmp.size() && tmp.back().first == B)
                    tmp[tmp.size() - 1].second = add(tmp.back().second, val);
                else tmp.emplace_back(B, val);
            }
            swap(dp[A], tmp);
        }

        for (auto [B, val] : dp[A]) {
//            cout << "dp " << bitset<2>(A) << ", " << bitset<2>(B) << " " << val << endl;
            for (int sub = B; sub; sub -= sub & (-sub)) {
                int cur = __builtin_ctz(sub), subFull = (1 << (cur + 1)) - 1;
                int leftNode = B ^ (B & subFull), newNode = bitmask[cur] ^ (bitmask[cur] & (A | (1 << cur)));
                dp[A | (1 << cur)].emplace_back(leftNode | newNode, val);
            }
            if (A == (1 << n) - 1 && B == 0) ans = val;
        }
    }
    cout << mul(mul(ans, inv2), m);

    return 0;
}
#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...