loj2540. "PKUWC2018"랜덤 알고리즘

문제의 의미

약간.

문제 해결

나는 독립적 인 시험 룸 세트의 폭력 발작이 90 점을 들었어요
국가 또는 하드의이 질문은 찾을 수 있습니다.
초기 정렬 웁니다. 설정 고려 ({난, S} F_ \를 \) 의 현재 상태를 나타내고, 각각 독립적으로 설정된다 \ (S \) , 더 이상 독립적 인 세트의 내부 (즉 \ (S \) 포인트 접속 측이다) 및 배치 구성원이 아닌 포인트의 수는 \ (I \) .
초기 상태가 \ (F_ {0, 0} =. 1 \) .
어떤 지점이 독립적으로 설정 한 다음에 첨가 될 수있는 경우, 전송을 고려 :
\ [F_ {S \ 컵 \ {X \}, I는 + \ 텍스트 {새로운 새} (X, S)} + = F_ {S, I} \ (X \ notin S) \]
여기서 \ (새 (X는, S) \) 대표 \ (X \) 연결된 측 및 속하지 않는 \ (S \) 와하지와 \ (S \) 임의 이 측면 포인트도의 점의 수. 이 조작을 나타내는 것 (X \) \ 배치 첨가한다. 만 이러한 작업이 충분히 더 이상 독립적 인 세트 내부에 고려되어야한다 없으며 점의 구성원이 아닌되어있는 경우, 배열에 가입 배치하지 (내가 \) \ 같은 점, 당신은 가입 중 하나를 선택할 수 있습니다. \ [F_ {S, I - 1} + = F_ {S, I} \]




고려하면 전송 반드시 DAG 구성 (프레스 세트 \ (S \) 부분의 순서를 다음 지점 \ (I \) 의 부분 순서)는 아무런 문제가 없다.
그러나, 전송의 방법은 연속적으로 수행을 동작 주목해야 할 때이므로 \ (I \) 에서 열거 방향 \ N- (\)\ (1 \) .
복잡성 \ (\ mathcal O (NN ^ 2 ^ 2) \) .

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;

const int N = 20, M = 1 << 20, mod = 998244353;
int n, m, c, ans, e[M], d[N][M], t[M], f[N][M];
int power (int x, int y) {
    int ret = 1;
    for ( ; y; y >>= 1, x = 1ll * x * x % mod) {
        if (y & 1) {
            ret = 1ll * ret * x % mod;
        }
    }
    return ret;
}
void U (int &x, int y) {
    if ((x += y) >= mod) {
        x -= mod;
    }
}
int main () {
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        e[1 << i] = 1 << i;
    }
    for (int i = 1, x, y; i <= m; ++i) {
        cin >> x >> y, --x, --y;
        e[1 << x] |= 1 << y, e[1 << y] |= 1 << x;
    }
    m = 1 << n;
    for (int i = 0; i < n; ++i) {
        for (int s = 0; s < m; ++s) {
            if (s >> i & 1) {
                e[s] |= e[s ^ 1 << i];
            }
        }
    }
    for (int i = 0; i < n; ++i) {
        for (int s = 0; s < m; ++s) {
            if (~e[s] >> i & 1) {
                d[i][s] = __builtin_popcount(e[s] | e[1 << i] ^ (1 << i)) - __builtin_popcount(e[s]);
            }
        }
    }
    f[0][0] = 1;
    for (int s = 0; s < m; ++s) {
        for (int i = n; i; --i) {
            U(f[i - 1][s], 1ll * f[i][s] * i % mod);
        }
        for (int i = n; ~i; --i) {
            if (f[i][s]) {
                for (int x = 0; x < n; ++x) {
                    if (~e[s] >> x & 1) {
                        U(f[i + d[x][s]][s | 1 << x], f[i][s]);
                    }
                }
            }
        }
    }
    for (int s = 0; s < m; ++s) {
        if (f[0][s]) {
            if (__builtin_popcount(s) > c) {
                c = __builtin_popcount(s), ans = 0;
            }
            if (__builtin_popcount(s) == c) {
                U(ans, f[0][s]);
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        ans = 1ll * ans * power(i, mod - 2) % mod;
    }
    cout << ans << endl;
    return 0;
}

추천

출처www.cnblogs.com/psimonw/p/12009216.html