結果

問題 No.753 最強王者決定戦
コンテスト
ユーザー 梧桐
提出日時 2026-06-20 17:33:00
言語 C++14
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++14 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 563 ms / 1,000 ms
コード長 1,665 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 459 ms
コンパイル使用メモリ 74,996 KB
実行使用メモリ 19,456 KB
最終ジャッジ日時 2026-06-20 17:33:06
合計ジャッジ時間 4,571 ms
ジャッジサーバーID
(参考情報)
judge2_0 / judge1_1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 4
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <iostream>
#include <cstdio>

using namespace std;

typedef long long LL;

const int N = 17, BB = 1 << N;

int a[N][N];
LL f[BB][N];

/**
 * 状压dp
 * f[mask][u],在mask的选手集合里u获胜的次数
 * 转移:
 *      1.把mask拆成两个子集A,B
 *      2.枚举A,B中的元素,j&k
 *      3.if (j 胜 k) dp[mask][j] += dp[A][j] * dp[B][k];
 *        else dp[mask][k] += dp[A][j] * dp[B][k];
 */

int main() {
    // freopen("knockout.in", "r", stdin);
    // freopen("knockout.out", "w", stdout);

    for (int i = 0; i < 16; ++i) {
        for (int j = 0; j < 16; ++j) {
            scanf("%d", &a[i][j]);
        }
    }

    for (int i = 0; i < 16; ++i) {
        for (int j = 0; j < i; ++j) {
            a[i][j] = -a[j][i];
        }
    }

    for (int i = 0; i < 16; ++i) {
        f[1 << i][i] = 1;
    }
    for (int len = 2; len <= N; len *= 2) {
        for (int mask = 0; mask < (1 << N); ++mask) {
            if (__builtin_popcount(mask) != len) continue;
            for (int A = mask; A; A = (A - 1) & mask) {
                if (__builtin_popcount(A) != len / 2) continue;
                int B = mask ^ A;
                for (int j = 0; j < N; ++j) {
                    if (!(A & (1 << j))) continue;
                    for (int k = 0; k < N; ++k) {
                        if (!(B & (1 << k))) continue;
                        if (a[j][k] == 1) f[mask][j] += f[A][j] * f[B][k];
                        else f[mask][k] += f[A][j] * f[B][k];
                    }
                }
            }
        }
    }

    for (int i = 0; i < 16; ++i) {
        printf("%lld\n", f[(1 << 16) - 1][i]);
    }

    return 0;
}
0