码迷,mamicode.com
首页 > 编程语言 > 详细

THUWC2018 随机算法

时间:2018-12-22 11:48:03      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:[1]   amp   算法   mes   https   code   ==   const   ||   

https://loj.ac/problem/2540

看了题解

题目大意

解法一

独立集那一套东西不是很好处理。为了消除加入一个点对之后点的影响,不妨在向独立集加入一个点时直接顺带加入和它相邻的点,用排列数预计算方案。

解法二

考虑一个集合的最后一个被加入独立集的点是什么。

实现

解法一:

#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 << ‘\n‘;
    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 随机算法

标签:[1]   amp   算法   mes   https   code   ==   const   ||   

原文地址:https://www.cnblogs.com/hfccccccccccccc/p/10159794.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!