PKUSC 2018 randomized algorithms

PKUSC 2018 randomized algorithms

\[ made \ by \ Ameiyo \]


Topic connection

A $ f [i] [s] $ $ I $ denotes has points which are arranged in the set maximum independent set of $ S $, the number of such programs.

For the current can not join the largest independent set point, after still can not join, so these points can be considered the same point, as you can use the same consumables.

The points can be added, which will join the largest independent set after larger point, directly into the $ s $ on the line.

#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
#define reg register
#define rep(i, a, b) for (reg int i = (a), i##end = (b); i <= i##end; ++i)
#define dep(i, a, b) for (reg int i = (a), i##end = (b); i >= i##end; --i)

template <typename _typer> inline _typer read() {
    _typer init = 0;
    char ch = getchar(), k = 0;
    for ( ; !isdigit(ch); ch = getchar()) k = (ch == '-');
    for ( ; isdigit(ch); ch = getchar())
        init = (init << 3) + (init << 1) + (ch ^ 48);
    return k ? -init : init;
}
const ll N = 25, INF = 1e9;
const ll M = (1 << 20), Mod = 998244353;

int n, m, G[N][N];
int tp[M], mk[N][M];
int f[N][M];

int Pow(int x, int k) {
    int ans = 1;
    for ( ; k > 0; x = 1ll * x * x % Mod, k >>= 1)
        ((k & 1) && (ans = 1ll * ans * x % Mod));
    return ans;
}

void Add(int &x, int y) { ((x += y) >= Mod && (x -= Mod)); }

int main() {
    n = read<int>(), m = read<int>();
    rep (i, 0, m - 1) {
        int x = read<int>() - 1, y = read<int>() - 1;
        G[x][y] = G[y][x] = true;
    }

    rep (i, 0, n - 1) tp[1 << i] = i, mk[i][0] = true;
    rep (i, 0, n - 1) rep (s, 1, (1 << n) - 1) if (!(s & (1 << i)))
        mk[i][s] = (mk[i][s & (s - 1)] && !G[i][tp[s & -s]]);

    f[0][0] = 1;
    // 不能放的点一直都不能放,所以可以算是一类点,就是把这部分处理掉就行了
    rep (i, 0, n - 1) rep (s, 0, (1 << n) - 1) if (f[i][s]) {
        reg int tmp = f[i][s], res = 0;
        rep (j, 0, n - 1) if (mk[j][s])
            ++res, Add(f[i + 1][s | (1 << j)], tmp);
        Add(f[i + 1][s], 1ll * tmp * (n - i - res) % Mod);
    }

    int Ans = 0, tot = 1, mx = 0;
    rep (i, 1, n) tot = 1ll * tot * i % Mod;
    rep (s, 0, (1 << n) - 1) if (f[n][s]) {
        int cnt = 0;
        for (int x = s; x > 0; x &= (x - 1)) ++cnt;
        if (cnt > mx) Ans = f[n][s], mx = cnt;
        else if (cnt == mx) Add(Ans, f[n][s]);
    }

//     cerr << Ans << endl;

    printf("%lld\n", 1ll * Ans * Pow(tot, Mod - 2) % Mod);
    return 0;
}

Note Luo Gu memory card, $ mk $ array open on No, but $ O (2 ^ n * n ^ 3) $ can too. . .


\[ in \ 2019.12.8 \]

Guess you like

Origin www.cnblogs.com/Ameiyo/p/12004561.html