혜성 콘테스트 # 11의 F arewell (DAG는 + FWT 서브셋 컨볼 루션을 계산)

포털.

해결 방법 :


YY 훈련은 DAG 카운트 때 에이프릴했고, 이것은 기본적으로 동일하지만 폭력이 직접 회선의 일부처럼 때 지방 달리 선거하지 않습니다하지 않습니다,이 쪽은에 확률의 선택된 부분 집합보다 더 회선.

DAG는 DAG의 사용을 계산하는 루틴 0도 지점입니다.

세트 \는 (F [S] \) 만 DAG의 실시 예를 형성하는 도트의 수가 엘리 시터들도 고려 나타낸다.

열거 \ (T | S ~ \ ~와 T = \ \ 빈) 이도 학위 포인트 0의 새로운 T입니다, 그들 사이에 모서리가 먼저이없는 한 다음 \ (T \)\ (S \) 없거나 구성 중 간의 측면 \ (T-> S \) , 표시 \ (CNT는 [S]가 \) 전달 계수가 에지들의 개수에 S를 나타낸다 :
{. 1 \}. \ (^ 위에 3 g {[T]} * { {2 \} ^ {3 위에 g [S + T]} 3 {2 위에 \ 위에} \ {g ^ [S] + g {T}}} \)

도가 다음 배제 용량 계수 포인트 0의 서브 세트를 열거 할 수 있기 때문에,이 가중치가 계산된다는 것을 유의 ((- 1) ^. {| T는 | + +1}이 \) \ 고려 \ (\ sum_ {I = (1)} ^ {| T |} (- 1) ^ {난 + 1} * C_ {| T |} ^ I = 1 \)를 증명한다.

다이렉트 컨볼 루션이다 \ (O (N-. ^ 3) \) , 그 이전 또는 루틴 FWT + 1 수, 복잡도이다 \ (O는 (N-2 ^^ * N-2) \) .

암호:


#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i <  B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int mo = 998244353;

ll ksm(ll x, ll y) {
    ll s = 1;
    for(; y; y /= 2, x = x * x % mo)
        if(y & 1) s = s * x % mo;
    return s;
}

const ll w1 = ksm(3, mo - 2), w2 = 2 * ksm(3, mo - 2) % mo;
const ll nw1 = ksm(w1, mo - 2), nw2 = ksm(w2, mo - 2);

const int N = 21;

const int M = 1 << 20;
int n, m, x, y, a2[N];
int bz[N][N];
ll f[M], nf[M], g[M];
int cnt[M];

void dft(int *a, int n, int f) {
    for(int h = 1; h < n; h *= 2) for(int j = 0; j < n; j += 2 * h) ff(i, 0, h) {
        if(f == 1) a[i + j + h] = (a[i + j + h] + a[i + j]) % mo; else
            a[i + j + h] = (a[i + j + h] - a[i + j]) % mo;
    }
}

int a[21][M], b[21][M];

int main() {
    scanf("%d %d", &n, &m);
    a2[0] = 1; fo(i, 1, n) a2[i] = a2[i - 1] * 2;
    fo(i, 1, m) {
        scanf("%d %d", &x, &y);
        x --; y --;
        bz[x][y] = 1;
    }
    ff(s, 1, a2[n]) cnt[s] = cnt[s - (s & -s)] + 1;
    ff(s, 0, a2[n]) {
        f[s] = g[s] = nf[s] = 1;
        if(s == 0) continue;
        int st;
        ff(i, 0, n) if(s >> i & 1) { st = i;}
        f[s] = f[s ^ (1 << st)];
        g[s] = g[s ^ (1 << st)];
        nf[s] = nf[s ^ (1 << st)];
        ff(i, 0, st) if(s >> i & 1) {
            if(bz[st][i]) f[s] = f[s] * w2 % mo, nf[s] = nf[s] * nw2 % mo, g[s] = g[s] * w1 % mo;
            if(bz[i][st]) f[s] = f[s] * w2 % mo, nf[s] = nf[s] * nw2 % mo, g[s] = g[s] * w1 % mo;
        }
    }
    fo(i, 1, n) {
        ff(j, 0, a2[n]) if(cnt[j] == i)
            b[i][j] = nf[j] * g[j] % mo * ((cnt[j] & 1) ? 1 : -1);
        dft(b[i], a2[n], 1);
    }
    a[0][0] = 1; dft(a[0], a2[n], 1);
    fo(w, 0, n) {
        fo(j, 1, n - w) {
            ff(i, 0, a2[n]) a[j + w][i] = ((ll) a[w][i] * b[j][i] + a[j + w][i]) % mo;
        }
    }
    dft(a[n], a2[n], -1);
    ll ans =  a[n][a2[n] - 1];
    ans = (ans % mo  + mo) * f[a2[n] - 1] % mo;
    pp("%lld\n", ans);
} 

추천

출처www.cnblogs.com/coldchair/p/11575289.html