結果
| 問題 |
No.2507 Yet Another Subgraph Counting
|
| コンテスト | |
| ユーザー |
emthrm
|
| 提出日時 | 2023-08-22 11:55:12 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 5,518 bytes |
| コンパイル時間 | 2,265 ms |
| コンパイル使用メモリ | 118,196 KB |
| 実行使用メモリ | 10,496 KB |
| 最終ジャッジ日時 | 2024-12-26 09:22:11 |
| 合計ジャッジ時間 | 22,884 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 47 TLE * 5 |
ソースコード
#include <algorithm>
#include <array>
#include <bit>
#include <cassert>
#include <concepts>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <utility>
#include <vector>
namespace emthrm {
template <int MaxN, typename T>
std::vector<T> subset_convolution(
const std::vector<T>& f, const std::vector<T>& g) {
using Polynomial = std::array<T, MaxN + 1>;
assert(std::has_single_bit(f.size()) && f.size() == g.size());
const int n = std::countr_zero(f.size());
assert(n <= MaxN);
const int domain_size = 1 << n;
const auto ranked_zeta_transform =
[n, domain_size](const std::vector<T>& f) -> std::vector<Polynomial> {
std::vector a(domain_size, Polynomial{});
for (int i = 0; i < domain_size; ++i) {
a[i][std::popcount(static_cast<unsigned int>(i))] = f[i];
}
for (int bit = 1; bit < domain_size; bit <<= 1) {
for (int i = 0; i < domain_size; ++i) {
if ((i & bit) == 0) {
for (int degree = 0; degree <= n; ++degree) {
a[i | bit][degree] += a[i][degree];
}
}
}
}
return a;
};
std::vector<Polynomial> a = ranked_zeta_transform(f);
const std::vector<Polynomial> b = ranked_zeta_transform(g);
for (int i = 0; i < domain_size; ++i) {
// Hadamard product
for (int degree_of_a = n; degree_of_a >= 0; --degree_of_a) {
const T tmp = std::exchange(a[i][degree_of_a], T{});
for (int degree_of_b = 0; degree_of_a + degree_of_b <= n; ++degree_of_b) {
a[i][degree_of_a + degree_of_b] += tmp * b[i][degree_of_b];
}
}
}
for (int bit = 1; bit < domain_size; bit <<= 1) {
for (int i = 0; i < domain_size; ++i) {
if ((i & bit) == 0) {
for (int degree = 0; degree <= n; ++degree) {
a[i | bit][degree] -= a[i][degree];
}
}
}
}
std::vector<T> c(domain_size);
for (int i = 0; i < domain_size; ++i) {
c[i] = a[i][std::popcount(static_cast<unsigned int>(i))];
}
return c;
}
template <int MaxN, typename T>
std::vector<T> exp_of_set_power_series(const std::vector<T>& f) {
assert(std::has_single_bit(f.size()) && f[0] == 0);
const int n = std::countr_zero(f.size());
assert(n <= MaxN);
std::vector<T> exponential{1};
exponential.reserve(1 << n);
for (int i = 0; i < n; ++i) {
std::ranges::copy(subset_convolution<MaxN>(
exponential,
std::vector(std::next(f.begin(), 1 << i),
std::next(f.begin(), 1 << (i + 1)))),
std::back_inserter(exponential));
}
return exponential;
}
} // namespace emthrm
bool KthBit(const std::unsigned_integral auto bit_field, const int k) {
return std::cmp_equal(bit_field >> k & 1, 1);
}
// <TLE?> #906824 ベース
// O(4^n n^2) 時間
int main() {
constexpr int kMaxN = 13;
int n, m;
std::cin >> n >> m;
assert(2 <= n && n <= kMaxN && 1 <= m && m <= n * (n - 1) / 2);
std::vector<std::uint32_t> graph(n);
while (m--) {
int u, v;
std::cin >> u >> v;
assert(1 <= u && u < v && v <= n);
--u; --v;
graph[u] |= UINT32_C(1) << v;
graph[v] |= UINT32_C(1) << u;
}
std::vector num_of_paths(1 << n, std::vector(n, INT64_C(0)));
for (int start = 0; start < n; ++start) {
num_of_paths[1 << start][start] = 1;
}
for (std::uint32_t bit = 1; bit < (UINT32_C(1) << n); ++bit) {
const int start = std::countr_zero(bit);
for (int current_vertex = start; current_vertex < n; ++current_vertex) {
for (int next_vertex = start + 1; next_vertex < n; ++next_vertex) {
if (!KthBit(bit, next_vertex) &&
KthBit(graph[current_vertex], next_vertex)) {
num_of_paths[bit | (1 << next_vertex)][next_vertex] +=
num_of_paths[bit][current_vertex];
}
}
}
}
std::vector<std::int64_t> num_of_cycles(1 << n, 0);
for (int vertex = 0; vertex < n; ++vertex) {
num_of_cycles[1 << vertex] = 1;
}
for (std::uint32_t bit = 7; bit < (UINT32_C(1) << n); ++bit) {
if (std::popcount(bit) < 3) continue;
const int start = std::countr_zero(bit);
for (int last = start + 1; last < n; ++last) {
if (KthBit(bit, last) && KthBit(graph[last], start)) {
num_of_cycles[bit] += num_of_paths[bit][last];
}
}
num_of_cycles[bit] /= 2;
}
std::vector<std::uint64_t> dp(1 << n, 0);
dp[1] = 1;
for (int vertex = 1; vertex < n; ++vertex) {
// O(4^k k^2) 時間
for (std::uint32_t cycle = UINT32_C(1) << vertex;
cycle < (UINT32_C(1) << (vertex + 1)); ++cycle) {
if (num_of_cycles[cycle] == 0) continue;
std::vector<int> on_cycle;
on_cycle.reserve(std::popcount(cycle));
for (int i = 0; i <= vertex; ++i) {
if (KthBit(cycle, i)) on_cycle.emplace_back(i);
}
std::vector<std::uint64_t> tmp(
dp.begin(), std::next(dp.begin(), 1 << vertex));
for (std::uint32_t i = 1; i < (UINT32_C(1) << vertex); ++i) {
if ((cycle & i) == UINT32_C(0)) {
int degree = 0;
for (const int v : on_cycle) degree += std::popcount(i & graph[v]);
tmp[i] *= degree;
}
}
tmp = emthrm::exp_of_set_power_series<kMaxN>(tmp);
for (std::uint32_t i = 0; i < (UINT32_C(1) << vertex); ++i) {
if ((cycle & i) == UINT32_C(0)) {
dp[cycle | i] += tmp[i] * num_of_cycles[cycle];
}
}
}
}
std::cout << emthrm::exp_of_set_power_series<kMaxN>(dp)[(1 << n) - 1] << '\n';
return 0;
}
emthrm