結果
| 問題 | No.753 最強王者決定戦 |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-06-20 17:33:00 |
| 言語 | C++14 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 563 ms / 1,000 ms |
| コード長 | 1,665 bytes |
| 記録 | |
| コンパイル時間 | 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 |
ソースコード
#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;
}