結果
問題 | No.2507 Yet Another Subgraph Counting |
ユーザー | 👑 emthrm |
提出日時 | 2023-08-22 11:55:12 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 5,518 bytes |
コンパイル時間 | 1,369 ms |
コンパイル使用メモリ | 118,068 KB |
実行使用メモリ | 10,624 KB |
最終ジャッジ日時 | 2024-06-07 22:52:24 |
合計ジャッジ時間 | 7,541 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
10,624 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 1 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 1 ms
5,376 KB |
testcase_07 | AC | 1 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 1 ms
5,376 KB |
testcase_11 | AC | 3 ms
5,376 KB |
testcase_12 | AC | 1 ms
5,376 KB |
testcase_13 | AC | 2 ms
5,376 KB |
testcase_14 | AC | 7 ms
5,376 KB |
testcase_15 | AC | 1 ms
5,376 KB |
testcase_16 | AC | 2 ms
5,376 KB |
testcase_17 | AC | 4 ms
5,376 KB |
testcase_18 | AC | 2 ms
5,376 KB |
testcase_19 | AC | 2 ms
5,376 KB |
testcase_20 | AC | 2 ms
5,376 KB |
testcase_21 | AC | 1 ms
5,376 KB |
testcase_22 | AC | 2 ms
5,376 KB |
testcase_23 | AC | 37 ms
5,376 KB |
testcase_24 | AC | 4 ms
5,376 KB |
testcase_25 | AC | 71 ms
5,376 KB |
testcase_26 | AC | 803 ms
5,376 KB |
testcase_27 | AC | 25 ms
5,376 KB |
testcase_28 | AC | 101 ms
5,376 KB |
testcase_29 | AC | 2 ms
5,376 KB |
testcase_30 | AC | 868 ms
5,376 KB |
testcase_31 | AC | 18 ms
5,744 KB |
testcase_32 | AC | 16 ms
5,620 KB |
testcase_33 | AC | 4 ms
5,376 KB |
testcase_34 | AC | 1 ms
5,376 KB |
testcase_35 | AC | 2 ms
5,376 KB |
testcase_36 | AC | 2 ms
5,376 KB |
testcase_37 | TLE | - |
testcase_38 | -- | - |
testcase_39 | -- | - |
testcase_40 | -- | - |
testcase_41 | -- | - |
testcase_42 | -- | - |
testcase_43 | -- | - |
testcase_44 | -- | - |
testcase_45 | -- | - |
testcase_46 | -- | - |
testcase_47 | -- | - |
testcase_48 | -- | - |
testcase_49 | -- | - |
testcase_50 | -- | - |
testcase_51 | -- | - |
ソースコード
#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; }