├── .github └── workflows │ └── verify.yml ├── .gitmodules ├── .verify-helper └── timestamps.remote.json ├── LICENSE ├── README.md ├── data_structure ├── binary_indexed_tree.hpp ├── binary_indexed_tree.test.cpp ├── convex_hull_trick.hpp ├── convex_hull_trick.line_add_get_min.test.cpp ├── convex_hull_trick.md ├── dual_segment_tree.hpp ├── dual_segment_tree.md ├── dual_segment_tree.range_update_query.test.cpp ├── dynamic_connectivity_offline.dynamic_graph_vertex_add_component_sum.test.cpp ├── dynamic_connectivity_offline.hpp ├── dynamic_connectivity_offline.md ├── euler_tour_subtree_query.hpp ├── euler_tour_subtree_query.md ├── euler_tour_subtree_query.vertex_add_subtree_sum.test.cpp ├── fully_indexable_dictionary.hpp ├── fully_indexable_dictionary.md ├── lazy_propagation_red_black_tree.hpp ├── lazy_propagation_red_black_tree.md ├── lazy_propagation_red_black_tree.range_affine_range_sum.test.cpp ├── lazy_propagation_segment_tree.hpp ├── lazy_propagation_segment_tree.md ├── lazy_propagation_segment_tree.range_affine_range_sum.test.cpp ├── lazy_propagation_segment_tree.range_min_range_add.test.cpp ├── li_chao_tree.hpp ├── li_chao_tree.md ├── li_chao_tree.segment_add_get_min.test.cpp ├── link_cut_tree.dynamic_tree_vertex_add_path_sum.test.cpp ├── link_cut_tree.dynamic_tree_vertex_set_path_composite.test.cpp ├── link_cut_tree.hpp ├── link_cut_tree.marked_ancestor.test.cpp ├── link_cut_tree.md ├── link_cut_tree.vertex_add_path_sum.test.cpp ├── link_cut_tree.vertex_set_path_composite.test.cpp ├── reporting_segment_tree.hpp ├── segment_tree.hpp ├── segment_tree.md ├── segment_tree.point_add_range_sum.test.cpp ├── segment_tree.point_set_range_composite.test.cpp ├── segment_tree.range_sum_query.test.cpp ├── segment_tree_beats.DSL_2_F.test.cpp ├── segment_tree_beats.DSL_2_G.test.cpp ├── segment_tree_beats.DSL_2_H.test.cpp ├── segment_tree_beats.DSL_2_I.test.cpp ├── segment_tree_beats.hpp ├── segment_tree_beats.md ├── segment_tree_beats.yosupo.test.cpp ├── sliding_window_aggregation.hpp ├── sliding_window_aggregation.yosupo.test.cpp ├── sparse_table.hpp ├── sparse_table.yosupo.test.cpp ├── sparse_table.yukicoder-1036.test.cpp ├── union_find_tree.aoj.test.cpp ├── union_find_tree.hpp ├── union_find_tree.md ├── union_find_tree.yosupo.test.cpp ├── union_find_tree_foldable_undoable.hpp ├── union_find_tree_with_monoid.hpp ├── wavelet_matrix.aoj2674.test.cpp ├── wavelet_matrix.hpp ├── wavelet_matrix.md ├── wavelet_matrix.range_kth_smallest.test.cpp └── wavelet_matrix.rectangle_sum.test.cpp ├── environment.sh ├── graph ├── bellman_ford.hpp ├── bellman_ford.test.cpp ├── cartesian_tree.hpp ├── cartesian_tree.yosupo.test.cpp ├── cartesian_tree.yukicoder-1031.test.cpp ├── catapillar_graph.hpp ├── connected_components.hpp ├── diameter_of_tree.hpp ├── dijkstra.hpp ├── dijkstra.yukicoder-1065.test.cpp ├── dinic.hpp ├── euler_graph.hpp ├── euler_tour_preorder.hpp ├── format.hpp ├── functional_graph.hpp ├── functional_graph.yuki1254.test.cpp ├── is_connected_graph.hpp ├── is_simple_graph.hpp ├── kruskal.aoj.test.cpp ├── kruskal.hpp ├── lowest_common_ancestor.aoj.test.cpp ├── lowest_common_ancestor.hpp ├── lowest_common_ancestor.yosupo.test.cpp ├── matrix_tree_theorem.hpp ├── minimum-cost-flow.hpp ├── quotient_graph.hpp ├── shortest_path_faster_algorithm.hpp ├── strongly_connected_components.hpp ├── strongly_connected_components.yosupo.test.cpp ├── subtree.hpp ├── topological_sort.hpp ├── transpose_graph.hpp ├── tree_decomposition.aoj_2405.test.cpp ├── tree_decomposition.hpp ├── tree_decomposition.md ├── virtual_trees.hpp ├── yen_algorithm.hpp └── yen_algorithm.yukicoder-1069.test.cpp ├── hack ├── fastio.hpp ├── fastio.yosupo.test.cpp ├── fastio_printer.hpp ├── fastio_scanner.hpp ├── fastio_scanner_and_printer.yosupo.test.cpp └── stack_pivot.hpp ├── library.pdf ├── modulus ├── bell_number.hpp ├── choose.hpp ├── choose.yukicoder-1035.test.cpp ├── choose_simple.hpp ├── factorial.hpp ├── formal_power_series.exp.test.cpp ├── formal_power_series.hpp ├── formal_power_series.inv.test.cpp ├── formal_power_series.log.test.cpp ├── formal_power_series.yukicoder-1145.test.cpp ├── garner.hpp ├── mint.hpp ├── mint_with_zero.hpp ├── mint_with_zero.test.cpp ├── modinv.hpp ├── modlog.hpp ├── modlog.yosupo.test.cpp ├── modlog.yuki1255.test.cpp ├── modpow.hpp ├── modsqrt.hpp ├── modsqrt.yosupo.test.cpp ├── multichoose.hpp ├── multichoose_simple.hpp ├── number_theoretic_transformation.hpp ├── number_theoretic_transformation.yosupo.test.cpp ├── number_theoretic_transformation_with_garner.hpp ├── number_theoretic_transformation_with_garner.yosupo.test.cpp ├── partition_number.hpp ├── permute.hpp ├── stirling_number_of_the_second_kind_convolution.hpp ├── stirling_number_of_the_second_kind_convolution.yosupo.test.cpp ├── stirling_number_of_the_second_kind_direct.hpp ├── stirling_number_of_the_second_kind_table.hpp ├── twelvefold_way.balls_and_boxes_1.test.cpp ├── twelvefold_way.balls_and_boxes_10.test.cpp ├── twelvefold_way.balls_and_boxes_11.test.cpp ├── twelvefold_way.balls_and_boxes_2.test.cpp ├── twelvefold_way.balls_and_boxes_3.test.cpp ├── twelvefold_way.balls_and_boxes_4.test.cpp ├── twelvefold_way.balls_and_boxes_5.test.cpp ├── twelvefold_way.balls_and_boxes_6.test.cpp ├── twelvefold_way.balls_and_boxes_7.test.cpp ├── twelvefold_way.balls_and_boxes_8.test.cpp ├── twelvefold_way.balls_and_boxes_9.test.cpp └── twelvefold_way.hpp ├── monoids ├── chmin_chmax_add.hpp ├── chmin_chmax_add_min_max_action.hpp ├── dual.hpp ├── gcd.hpp ├── left.hpp ├── left_action.hpp ├── linear_function.hpp ├── linear_function_plus_count_action.hpp ├── matrix_template.hpp ├── max.hpp ├── max_index.hpp ├── min.hpp ├── min_count.hpp ├── min_index.hpp ├── min_max.hpp ├── plus.hpp ├── plus_count.hpp ├── plus_max_action.hpp ├── plus_min_action.hpp ├── plus_min_count_action.hpp ├── product.hpp ├── reversible.hpp ├── trivial.hpp └── trivial_action.hpp ├── number ├── fast_fourier_transformation.hpp ├── fast_fourier_transformation.yukicoder-856.test.cpp ├── gcd.hpp ├── inversion_number.hpp ├── karatsuba.hpp ├── lagrange_interpolation.hpp ├── matrix.hpp ├── matrix.yukicoder-1073.test.cpp ├── matrix_template.hpp ├── matrix_template.yukicoder-1073.test.cpp ├── miller-rabin.hpp ├── primes.aoj.test.cpp ├── primes.hpp ├── primes.yukicoder-1140.test.cpp ├── primes_extra.hpp └── primes_extra.yukicoder-1659.test.cpp ├── old ├── a.inc.cpp ├── aho-corasick.inc.cpp ├── bernoulli-number.inc.cpp ├── bipartite-graph.inc.cpp ├── boyer-moore.inc.cpp ├── breadth-first-search.inc.cpp ├── centers.inc.cpp ├── centroid-decomposition.inc.cpp ├── comparable-view.inc.cpp ├── convex-hull-trick-with-monotonicity.inc.cpp ├── convex-hull.inc.cpp ├── cumulative-sum.inc.cpp ├── dice.inc.cpp ├── digit-dp.inc.cpp ├── dijkstra.inc.cpp ├── distributed-code-jam.inc.cpp ├── dlopen.inc.cpp ├── dominator-tree.inc.cpp ├── double-ended-priority-queue.inc.cpp ├── doubling.inc.cpp ├── dynamic-segment-tree.inc.cpp ├── euler-tour.inc.cpp ├── extgcd.inc.cpp ├── factoradic.inc.cpp ├── factorial-embed.inc.cpp ├── fast-mobius-transformation.inc.cpp ├── ford-fulkerson.inc.cpp ├── graphviz.inc.cpp ├── heavy_light_decomposition.inc.cpp ├── iterate.inc.cpp ├── knapsack-problem-branch-and-bound.inc.cpp ├── knuth-morris-pratt.inc.cpp ├── linear-weighted-sum.inc.cpp ├── longest-increasing-subsequence.inc.cpp ├── marathon.inc.cpp ├── matrix.inc.cpp ├── maximum-independent-set.inc.cpp ├── midpoint.inc.cpp ├── palindrome.inc.cpp ├── periodic-function-power.inc.cpp ├── persistent-array.inc.cpp ├── persistent-randomized-binary-search-tree.inc.cpp ├── point-int.inc.cpp ├── polya-enumeration.inc.cpp ├── popen2.inc.cpp ├── primes-small.inc.cpp ├── range-union-find-tree.inc.cpp ├── rational.inc.cpp ├── red-black-tree.inc.cpp ├── rollback-square-decomposition.inc.cpp ├── rollback-square-decomposition.yukicoder-1031.test.cpp ├── rolling-hash.inc.cpp ├── segment-tree-2d.inc.cpp ├── simplex.inc.cpp ├── skew-heap.inc.cpp ├── sliding-window.inc.cpp ├── string-skip-list.inc.cpp ├── subset.inc.cpp ├── suffix-array.inc.cpp ├── ternary-search.inc.cpp ├── treap.inc.cpp ├── tree-dp.inc.cpp ├── trie-tree.inc.cpp ├── two-edge-connected-components.inc.cpp ├── two-node-connected-components.inc.cpp ├── warshall-floyd.inc.cpp └── xorshift.inc.cpp ├── printout.sh ├── python ├── binary_search.py ├── chinese_remainder_theorem.py ├── choose.py ├── extgcd.py ├── matrix-modinv.py ├── miller_rabin.py └── rational-gcd.py ├── string ├── longest_common_prefix.hpp ├── longest_common_prefix.yosupo.test.cpp ├── suffix_array.hpp └── suffix_array.yosupo.test.cpp ├── template.cpp └── utils ├── binary_search.aoj.test.cpp ├── binary_search.hpp ├── binary_search_float.hpp ├── binary_search_max.hpp ├── coordinate_compression.hpp ├── dsu_on_tree.aoj.test.cpp ├── dsu_on_tree.hpp ├── fast_zeta_transform.hpp ├── interval_map.hpp ├── interval_set.hpp ├── left_to_right_maxima.hpp ├── macros.hpp ├── mex.hpp ├── mex_calculator.hpp ├── mo_algorithm.hpp ├── mo_algorithm.yuki1270.test.cpp ├── next_combination.hpp ├── two_satisfiability.hpp └── two_satisfiability.yosupo.test.cpp /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: verify 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v1 11 | 12 | - name: Set up Python 13 | uses: actions/setup-python@v1 14 | 15 | - name: Install dependencies 16 | run: pip3 install -U git+https://github.com/kmyk/online-judge-verify-helper 17 | 18 | - name: Run tests 19 | env: 20 | GH_PAT: ${{ secrets.GH_PAT }} 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | YUKICODER_TOKEN: ${{ secrets.YUKICODER_TOKEN }} 23 | DROPBOX_TOKEN: ${{ secrets.DROPBOX_TOKEN }} 24 | run: oj-verify all -j 2 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Togasat"] 2 | path = Togasat 3 | url = https://github.com/togatoga/Togasat 4 | [submodule "tinydfa"] 5 | path = tinydfa 6 | url = https://github.com/kmyk/tinydfa 7 | [submodule "ac-library"] 8 | path = ac-library 9 | url = https://github.com/atcoder/ac-library 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014-2019 Kimiyuki Onaka 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Competitive Programming Library 2 | 3 | [![Actions Status](https://github.com/kmyk/competitive-programming-library/workflows/verify/badge.svg)](https://github.com/kmyk/competitive-programming-library/actions) 4 | [![GitHub Pages](https://img.shields.io/static/v1?label=GitHub+Pages&message=+&color=brightgreen&logo=github)](https://kmyk.github.io/competitive-programming-library/) 5 | ![License](https://img.shields.io/github/license/kmyk/competitive-programming-library.svg) 6 | 7 | You can use [the documents](https://kmyk.github.io/competitive-programming-library/) generated by [kmyk/online-judge-verify-helper](https://github.com/kmyk/online-judge-verify-helper). 8 | 9 | ## License 10 | 11 | Licensed under MIT License, but you can use this library without the copyright notice in your submissions for online judges. 12 | -------------------------------------------------------------------------------- /data_structure/binary_indexed_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | /** 7 | * @brief Binary Indexed Tree 8 | */ 9 | template 10 | struct binary_indexed_tree { 11 | typedef typename CommutativeMonoid::value_type value_type; 12 | CommutativeMonoid mon; 13 | std::vector data; 14 | binary_indexed_tree(int n, CommutativeMonoid const & mon_ = CommutativeMonoid()) 15 | : mon(mon_), 16 | data(n, mon.unit()) { 17 | } 18 | template 19 | binary_indexed_tree(InputIterator first, InputIterator last, CommutativeMonoid const & mon_ = CommutativeMonoid()) 20 | : mon(mon_), 21 | data(first, last) { 22 | REP3 (j, 1, data.size() + 1) { 23 | int k = j + (j & -j); 24 | if (k - 1 < static_cast(data.size())) { 25 | data[k - 1] = mon.mult(data[k - 1], data[j - 1]); 26 | } 27 | } 28 | } 29 | /** 30 | * @note $a_i \gets a_i + z$ 31 | * @note $O(\log N)$ 32 | */ 33 | void point_mult(int i, value_type z) { 34 | assert (0 <= i and i < static_cast(data.size())); 35 | for (int j = i + 1; j <= static_cast(data.size()); j += j & -j) { 36 | data[j - 1] = mon.mult(data[j - 1], z); 37 | } 38 | } 39 | /** 40 | * @note $\sum _ {i \lt r} a_i$ 41 | * @note $O(\log N)$ 42 | */ 43 | value_type initial_range_get(int r) { 44 | assert (0 <= r and r <= static_cast(data.size())); 45 | value_type acc = mon.unit(); 46 | for (int i = r; 0 < i; i -= i & -i) { 47 | acc = mon.mult(data[i - 1], acc); 48 | } 49 | return acc; 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /data_structure/binary_indexed_tree.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | #include 3 | #include 4 | #include 5 | #include "../data_structure/binary_indexed_tree.hpp" 6 | #include "../monoids/plus.hpp" 7 | #include "../utils/macros.hpp" 8 | using namespace std; 9 | 10 | int main() { 11 | int n, q; scanf("%d%d", &n, &q); 12 | vector a(n); 13 | REP (i, n) { 14 | scanf("%lld", &a[i]); 15 | } 16 | binary_indexed_tree > bit(ALL(a)); 17 | while (q --) { 18 | int t, x, y; scanf("%d%d%d", &t, &x, &y); 19 | if (t == 0) { 20 | bit.point_mult(x, y); 21 | } else if (t == 1) { 22 | long long answer = bit.initial_range_get(y) - bit.initial_range_get(x); 23 | printf("%lld\n", answer); 24 | } 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /data_structure/convex_hull_trick.line_add_get_min.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/line_add_get_min" 2 | #include "../data_structure/convex_hull_trick.hpp" 3 | #include "../utils/macros.hpp" 4 | #include 5 | 6 | int main() { 7 | int n, q; scanf("%d%d", &n, &q); 8 | convex_hull_trick cht; 9 | REP (i, n) { 10 | int64_t a, b; scanf("%lld%lld", &a, &b); 11 | cht.add_line(a, b); 12 | } 13 | while (q --) { 14 | int t; scanf("%d", &t); 15 | if (t == 0) { 16 | int64_t a, b; scanf("%lld%lld", &a, &b); 17 | cht.add_line(a, b); 18 | } else if (t == 1) { 19 | int64_t p; scanf("%lld", &p); 20 | printf("%lld\n", cht.get_min(p)); 21 | } else { 22 | assert (false); 23 | } 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /data_structure/convex_hull_trick.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | 一次関数の集合 $F = \emptyset \subseteq \lbrace \lambda x. ax + b \mid a, b \in \mathbb{Z} \rbrace$ に対し、次が $O(\log N)$ amortized (一部は $O(\log N)$) で処理可能: 4 | 5 | - $\mathtt{add\unicode{95}line}(f)$: $F \gets F \cup \lbrace f \rbrace$ と更新する。 6 | - $\mathtt{get\unicode{95}min}(x)$: 最小値 $\min _ {f \in F} f(x)$ を計算する。 7 | -------------------------------------------------------------------------------- /data_structure/dual_segment_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * @brief Dual Segment Tree / 双対セグメント木 (monoids, 完全二分木) 8 | * @docs data_structure/dual_segment_tree.md 9 | * @tparam Monoid (commutativity is not required) 10 | */ 11 | template 12 | struct dual_segment_tree { 13 | typedef typename Monoid::value_type value_type; 14 | const Monoid mon; 15 | int n; 16 | std::vector f; 17 | dual_segment_tree() = default; 18 | dual_segment_tree(int n_, const Monoid & mon_ = Monoid()) : mon(mon_) { 19 | n = 1; while (n < n_) n *= 2; 20 | f.resize(2 * n - 1, mon.unit()); 21 | } 22 | value_type point_get(int i) { // 0-based 23 | assert (0 <= i and i < n); 24 | value_type acc = mon.unit(); 25 | for (i += n; i > 0; i /= 2) { // 1-based 26 | acc = mon.mult(f[i - 1], acc); 27 | } 28 | return acc; 29 | } 30 | void range_apply(int l, int r, value_type g) { // 0-based, [l, r) 31 | assert (0 <= l and l <= r and r <= n); 32 | range_apply(0, 0, n, l, r, g); 33 | } 34 | void range_apply(int i, int il, int ir, int l, int r, value_type g) { 35 | if (l <= il and ir <= r) { // 0-based 36 | f[i] = mon.mult(g, f[i]); 37 | } else if (ir <= l or r <= il) { 38 | // nop 39 | } else { 40 | range_apply(2 * i + 1, il, (il + ir) / 2, 0, n, f[i]); 41 | range_apply(2 * i + 2, (il + ir) / 2, ir, 0, n, f[i]); 42 | f[i] = mon.unit(); 43 | range_apply(2 * i + 1, il, (il + ir) / 2, l, r, g); 44 | range_apply(2 * i + 2, (il + ir) / 2, ir, l, r, g); 45 | } 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /data_structure/dual_segment_tree.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | monoid $F = (F, \circ, \mathrm{id})$ の要素の列 $f = (f_0, f_1, \dots, f _ {n - 1}) \in F^n$ に対し、次が $O(\log N)$ で処理可能: 4 | 5 | - $\mathtt{range\unicode{95}set}(l, r, g)$: それぞれの $i \in [l, r)$ に対し $f_i \gets g \circ f_i$ と更新する。 6 | - $\mathtt{point\unicode{95}get}(i)$: 値 $f_i$ を計算する。 7 | -------------------------------------------------------------------------------- /data_structure/dual_segment_tree.range_update_query.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_D" 2 | #include "../data_structure/dual_segment_tree.hpp" 3 | #include "../monoids/left.hpp" 4 | 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | int n, q; cin >> n >> q; 10 | dual_segment_tree > segtree(n); 11 | segtree.range_apply(0, n, make_pair(true, (1u << 31) - 1)); 12 | while (q --) { 13 | int com; cin >> com; 14 | if (com == 0) { 15 | int l, r; uint32_t x; cin >> l >> r >> x; 16 | ++ r; 17 | segtree.range_apply(l, r, make_pair(true, x)); 18 | } else if (com == 1) { 19 | int i; cin >> i; 20 | cout << segtree.point_get(i).second << endl; 21 | } 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /data_structure/dynamic_connectivity_offline.dynamic_graph_vertex_add_component_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/dynamic_graph_vertex_add_component_sum" 2 | #include "../data_structure/dynamic_connectivity_offline.hpp" 3 | #include "../monoids/plus.hpp" 4 | #include "../hack/fastio.hpp" 5 | #include "../utils/macros.hpp" 6 | 7 | int main() { 8 | int n = in(); 9 | int q = in(); 10 | 11 | dynamic_connectivity_offline > dycon(n); 12 | REP (v, n) { 13 | int64_t a = in(); 14 | dycon.point_set(v, a); 15 | } 16 | REP (i, q) { 17 | int t = in(); 18 | if (t == 0) { 19 | int u = in(); 20 | int v = in(); 21 | dycon.link(u, v); 22 | } else if (t == 1) { 23 | int u = in(); 24 | int v = in(); 25 | dycon.cut(u, v); 26 | } else if (t == 2) { 27 | int v = in(); 28 | int64_t x = in(); 29 | dycon.point_mult(v, x); 30 | } else if (t == 3) { 31 | int v = in(); 32 | dycon.component_get(v); 33 | } else { 34 | assert (false); 35 | } 36 | } 37 | 38 | std::vector answer = dycon.run(); 39 | for (int64_t a : answer) { 40 | out(a); 41 | out('\n'); 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /data_structure/dynamic_connectivity_offline.md: -------------------------------------------------------------------------------- 1 | ## Operations 2 | 3 | 単純無向グラフ $G = (V, E)$ であって頂点 $x \in V$ に可換 monoid $M = (M, +, 0)$ による重み $a_x \in M$ が付いたものに対し、次のクエリが offline で全体で $O(Q \log Q)$ で処理可能: 4 | 5 | - $\mathtt{link}(x, y)$: 頂点 $x, y$ 間に辺 $\lbrace x, y \rbrace$ を追加する。 6 | - $\mathtt{cut}(x, y)$: 頂点 $x, y$ 間から辺 $\lbrace x, y \rbrace$ を削除する。 7 | - $\mathtt{point\unicode{95}set}(x, b)$: 頂点 $x$ の重みを $a_x \gets b$ と更新する。 8 | - $\mathtt{point\unicode{95}mult}(x, b)$: 頂点 $x$ の重みを $a_x \gets a_x + b$ と更新する。 9 | - $\mathtt{component\unicode{95}get}(x)$: 頂点 $x$ と同じ連結成分 $C \subseteq V$ に所属する頂点の重みの総和 $\sum _ {x \in C} a_x$ を計算する。 10 | 11 | ただし offline であるので、計算結果は最後に $\mathtt{run}()$ を呼ぶことで取得する。 12 | -------------------------------------------------------------------------------- /data_structure/euler_tour_subtree_query.md: -------------------------------------------------------------------------------- 1 | ## Operations 2 | 3 | 根付き木 $T$ であってそれぞれの頂点 $x$ に可換 monoid 重み $a_x \in M$ が乗ったものがあるとする。頂点数を $N$ として均し $O(\log N)$ で次が処理できる。 4 | 5 | - $\mathtt{vertex\unicode{95}set}(x, b)$: 頂点 $x$ の重みを $a_x \gets b$ と更新する。 6 | - $\mathtt{vertex\unicode{95}get}(x)$: 頂点 $x$ の重み $a_x$ を計算する。 7 | - $\mathtt{subtree\unicode{95}get}(x, y)$: 頂点 $x$ を根とする部分木に属する頂点の重みの総和 $$\sum _ {y ~\text{is a descendent of}~ x} a_y$$ を計算する。 8 | -------------------------------------------------------------------------------- /data_structure/euler_tour_subtree_query.vertex_add_subtree_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/vertex_add_subtree_sum" 2 | #include "../data_structure/euler_tour_subtree_query.hpp" 3 | #include "../monoids/plus.hpp" 4 | #include "../utils/macros.hpp" 5 | #include "../hack/fastio.hpp" 6 | #include 7 | using namespace std; 8 | 9 | int main() { 10 | int n = in(); 11 | int q = in(); 12 | 13 | // initialize 14 | vector a(n); 15 | REP (i, n) { 16 | a[i] = in(); 17 | } 18 | vector > g(n); 19 | REP3 (i, 1, n) { 20 | int p_i = in(); 21 | g[i].push_back(p_i); 22 | g[p_i].push_back(i); 23 | } 24 | constexpr int root = 0; 25 | euler_tour_subtree_query > euler(g, root, ALL(a)); 26 | 27 | // answer to queries 28 | while (q --) { 29 | int t = in(); 30 | if (t == 0) { 31 | int u = in(); 32 | int64_t x = in(); 33 | euler.vertex_set(u, euler.vertex_get(u) + x); 34 | } else if (t == 1) { 35 | int u = in(); 36 | out(euler.subtree_get(u)); 37 | out('\n'); 38 | } 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /data_structure/fully_indexable_dictionary.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | 長さ $N$ の bit 列 $b = (b_0, b_1, \dots, b _ {n - 1}) \in 2^N$ に対し、次が $O(1)$ で処理可能: 4 | 5 | - $\mathtt{rank}(l, r)$: 区間 $\lbrack l, r)$ 中の値 $1$ の出現回数 $$\unicode{35} \lbrace i \in \lbrack l, r) \mid a_i = 1 \rbrace$$ を計算する。 6 | - $\mathtt{select}(k)$: 位置 $l$ 以降で $k \ge 0$ 番目に出現する値 $1$ の位置 $i$ (つまり $i \ge l$ かつ $a_i = 1$ かつ $$\unicode{35} \lbrace j \in \lbrack l, i) \mid a_j = 1 \rbrace = k$$ を満たす $i$) を計算する。 7 | - ただし今回の実装では妥協の結果 $O(\log N)$ になっている 8 | - $\mathtt{access}(i)$: 値 $b_i$ を計算する。 9 | -------------------------------------------------------------------------------- /data_structure/lazy_propagation_red_black_tree.md: -------------------------------------------------------------------------------- 1 | ## Operations 2 | 3 | 完全二分木上の遅延伝播セグメント木でできることに加え、$O(\log N)$ で次ができる: 4 | 5 | - $\mathtt{insert}(i, b)$: 列の $i$ 番目の要素の前に要素 $b$ を挿入する。 6 | - $\mathtt{erase}(i)$: 列の $i$ 番目の要素を削除する。 7 | - $\mathtt{reverse}(l, r)$: 列の $l, l+1, \dots, r-1$ 番目の要素を反転する。つまり $(a_0, a_1, \dots, a _ {l-1}, a_l, a _ {l+1}, \dots, a _ {r-1}, a_r, a _ {r + 1}, \dots, a _ {N - 1}) \gets (a_0, a_1, \dots, a _ {l-1}, a _ {r-1}, a _ {r-2}, \dots, a_l, a_r, a _ {r + 1}, \dots, a _ {N - 1})$ と更新する。 8 | -------------------------------------------------------------------------------- /data_structure/lazy_propagation_red_black_tree.range_affine_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum" 2 | #include "../data_structure/lazy_propagation_red_black_tree.hpp" 3 | #include "../monoids/plus_count.hpp" 4 | #include "../monoids/linear_function.hpp" 5 | #include "../monoids/linear_function_plus_count_action.hpp" 6 | #include "../modulus/mint.hpp" 7 | #include "../utils/macros.hpp" 8 | #include 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | constexpr int MOD = 998244353; 14 | 15 | int main() { 16 | int n, q; scanf("%d%d", &n, &q); 17 | vector, int> > a(n); 18 | REP (i, n) { 19 | int a_i; scanf("%d", &a_i); 20 | a[i].first = a_i; 21 | a[i].second = 1; 22 | } 23 | lazy_propagation_red_black_tree >, linear_function_monoid >, linear_function_plus_count_action > > segtree(ALL(a)); 24 | while (q --) { 25 | int t; scanf("%d", &t); 26 | if (t == 0) { 27 | int l, r, b, c; scanf("%d%d%d%d", &l, &r, &b, &c); 28 | pair, mint > f(b, c); 29 | segtree.range_apply(l, r, f); 30 | } else if (t == 1) { 31 | int l, r; scanf("%d%d", &l, &r); 32 | mint answer = segtree.range_get(l, r).first; 33 | printf("%d\n", answer.value); 34 | } 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /data_structure/lazy_propagation_segment_tree.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | 次があるとする: 4 | 5 | - monoid $M = (M, \cdot, 1)$ 6 | - monoid $F = (F, \circ, \mathrm{id})$ 7 | - monoid $F$ の半群 $M$ に対する作用 $\star$。つまり関数 $\star : F \times M \to M$ であって、次を満たすもの 8 | - $\forall a \in M.~ \mathrm{id} \star a = a$ 9 | - $\forall f, g \in F.~ \forall a \in M.~ (f \circ g) \star a = f \star (g \star a)$ 10 | - $\forall f \in F.~ \forall a, b \in M.~ f \star (a \cdot b) = (f \star a) \cdot (f \star b)$ 11 | 12 | このとき monoid $M$ の要素の列 $a = (a_0, a_1, \dots, a _ {n - 1}) \in M^n$ に対し、次が $O(\log N)$ で処理可能: 13 | 14 | - $\mathtt{range\unicode{95}apply}(l, r, g)$: それぞれの $i \in [l, r)$ に対し $a_i \gets g \star a_i$ と更新する。 15 | - $\mathtt{range\unicode{95}get}(l, r)$: 積 $a_l \cdot a _ {l + 1} \cdot \dots \cdot a _ {r - 1}$ を計算する。 16 | 17 | 他にも: 18 | 19 | - $\mathtt{point\unicode{95}get}(i)$: 値 $a_i$ を計算する。 20 | - $\mathtt{point\unicode{95}set}(i, b)$: $a_i \gets b$ と更新する。 21 | - $\mathtt{range\unicode{95}set}(l, r, b)$: それぞれの $i \in [l, r)$ に対し $a_i \gets b$ と更新する。 22 | -------------------------------------------------------------------------------- /data_structure/lazy_propagation_segment_tree.range_affine_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum" 2 | #include "../data_structure/lazy_propagation_segment_tree.hpp" 3 | #include "../monoids/plus_count.hpp" 4 | #include "../monoids/linear_function.hpp" 5 | #include "../monoids/linear_function_plus_count_action.hpp" 6 | #include "../modulus/mint.hpp" 7 | #include "../utils/macros.hpp" 8 | #include 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | constexpr int MOD = 998244353; 14 | 15 | int main() { 16 | int n, q; scanf("%d%d", &n, &q); 17 | vector, int> > a(n); 18 | REP (i, n) { 19 | int a_i; scanf("%d", &a_i); 20 | a[i].first = a_i; 21 | a[i].second = 1; 22 | } 23 | lazy_propagation_segment_tree >, linear_function_monoid >, linear_function_plus_count_action > > segtree(ALL(a)); 24 | while (q --) { 25 | int t; scanf("%d", &t); 26 | if (t == 0) { 27 | int l, r, b, c; scanf("%d%d%d%d", &l, &r, &b, &c); 28 | pair, mint > f(b, c); 29 | segtree.range_apply(l, r, f); 30 | } else if (t == 1) { 31 | int l, r; scanf("%d%d", &l, &r); 32 | mint answer = segtree.range_get(l, r).first; 33 | printf("%d\n", answer.value); 34 | } 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /data_structure/lazy_propagation_segment_tree.range_min_range_add.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_H" 2 | #include "../data_structure/lazy_propagation_segment_tree.hpp" 3 | #include "../monoids/min.hpp" 4 | #include "../monoids/plus.hpp" 5 | #include "../monoids/plus_min_action.hpp" 6 | #include 7 | 8 | int main() { 9 | int n, q; scanf("%d%d", &n, &q); 10 | lazy_propagation_segment_tree, plus_monoid, plus_min_action > segtree(n); 11 | segtree.range_set(0, n, 0); 12 | while (q --) { 13 | int com, l, r; scanf("%d%d%d", &com, &l, &r); 14 | ++ r; 15 | if (com == 0) { 16 | int x; scanf("%d", &x); 17 | segtree.range_apply(l, r, x); 18 | } else if (com == 1) { 19 | printf("%d\n", segtree.range_get(l, r)); 20 | } 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /data_structure/li_chao_tree.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | ありえる座標の有限集合 $X \subseteq \mathbb{Z}$ が固定されているとする。 4 | 一次関数と区間の対の集合 $F = \emptyset \subseteq \lbrace \lbrack l, r) \mid l, r \in X \wedge l \le r \rbrace \times \lbrace \lambda x. ax + b \mid a, b \in \mathbb{Z} \rbrace$ に対し、次が $O(\log N)$ amortized (一部は $O(\log N)$) で処理可能: 5 | 6 | - $\mathtt{add\unicode{95}segment}(l, r, f)$: $l, r \in X$ でなければならない。$F \gets F \cup \lbrace (f, \lbrack l, r) \rbrace$ と更新する。 7 | - $\mathtt{get\unicode{95}min}(x)$: $x \in X$ でなければならない。$$\min _ {(f, \lbrack l, r) \in F \wedge x \lbrack l, r))} f(x)$$ を $O(\log N)$ で計算する。 8 | -------------------------------------------------------------------------------- /data_structure/link_cut_tree.dynamic_tree_vertex_add_path_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/dynamic_tree_vertex_add_path_sum" 2 | #include "../data_structure/link_cut_tree.hpp" 3 | #include "../monoids/plus.hpp" 4 | #include "../utils/macros.hpp" 5 | #include "../hack/fastio.hpp" 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int main() { 11 | int n = in(); 12 | int q = in(); 13 | 14 | // initialize 15 | link_cut_tree > lct(n); 16 | REP (i, n) { 17 | int64_t a_i = in(); 18 | lct.vertex_set(i, a_i); 19 | } 20 | vector > g(n); 21 | REP (i, n - 1) { 22 | int u = in(); 23 | int v = in(); 24 | g[u].push_back(v); 25 | g[v].push_back(u); 26 | } 27 | vector used(n); 28 | stack stk; 29 | stk.push(0); 30 | used[0] = true; 31 | while (not stk.empty()) { 32 | int u = stk.top(); 33 | stk.pop(); 34 | for (int v : g[u]) if (not used[v]) { 35 | lct.link(v, u); 36 | stk.push(v); 37 | used[v] = true; 38 | } 39 | } 40 | 41 | // answer to queries 42 | while (q --) { 43 | int t = in(); 44 | if (t == 0) { 45 | int u = in(); 46 | int v = in(); 47 | int w = in(); 48 | int x = in(); 49 | lct.cut(lct.get_parent(u) == v ? u : v); 50 | lct.evert(w); 51 | lct.link(w, x); 52 | } else if (t == 1) { 53 | int p = in(); 54 | int64_t x = in(); 55 | lct.vertex_set(p, lct.vertex_get(p) + x); 56 | } else if (t == 2) { 57 | int u = in(); 58 | int v = in(); 59 | out(lct.path_get(u, v)); 60 | out('\n'); 61 | } 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /data_structure/link_cut_tree.marked_ancestor.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2170&lang=jp" 2 | #include 3 | #include "../data_structure/link_cut_tree.hpp" 4 | #include "../monoids/trivial.hpp" 5 | #include "../utils/macros.hpp" 6 | using namespace std; 7 | 8 | 9 | int main() { 10 | while (true) { 11 | int n, q; cin >> n >> q; 12 | if (n == 0 and q == 0) break; 13 | 14 | link_cut_tree lct(n); 15 | REP3 (i, 1, n) { 16 | int parent; cin >> parent; 17 | -- parent; 18 | lct.link(i, parent); 19 | } 20 | 21 | long long sum = 0; 22 | vector marked(n); 23 | marked[0] = true; 24 | while (q --) { 25 | char c; int v; cin >> c >> v; 26 | -- v; 27 | if (c == 'M') { 28 | if (not marked[v]) { 29 | marked[v] = true; 30 | lct.cut(v); 31 | } 32 | } else if (c == 'Q') { 33 | sum += lct.get_root(v) + 1; 34 | } 35 | } 36 | cout << sum << endl; 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /data_structure/link_cut_tree.md: -------------------------------------------------------------------------------- 1 | ## Operations 2 | 3 | 根付き木からなる森 $G$ を動的に操作できる。頂点数を $N$ として均し $O(\log N)$ で次が処理できる。 4 | 5 | - $\mathtt{link}(x, y)$: 根である頂点 $x$ から頂点 $y$ に辺を追加する。 6 | - $\mathtt{cut}(x)$: 根でない頂点 $x$ とその親との間の辺を削除する。 7 | - この森における接続性についての様々な質問 8 | - $\mathtt{get\unicode{95}parent}(x)$ 9 | - $\mathtt{get\unicode{95}root}(x)$ 10 | - $\mathtt{are\unicode{95}connected}(x, y)$ 11 | - $\mathtt{get\unicode{95}lowest\unicode{95}common\unicode{95}ancestor}(x, y)$ 12 | - $\mathtt{evert}(x)$: 頂点 $x$ を根にする。つまり、頂点 $x$ からその所属する木の根までの辺をすべて反転させる。 13 | 14 | 加えて、それぞれの頂点 $x$ に monoid 値重み $a_x \in M$ を乗せて、次が処理できる。 15 | 16 | - $\mathtt{vertex\unicode{95}set}(x, b)$: 頂点 $x$ の重みを $a_x \gets b$ と更新する。 17 | - $\mathtt{vertex\unicode{95}get}(x, b)$: 頂点 $x$ の重み $a_x \gets b$ を計算する。 18 | - $\mathtt{path\unicode{95}get}(x, y)$: 頂点 $x$ から $y$ への唯一のパス $x, z_1, z_2, \dots, y$ に沿った重みの積 $a_x \cdot a _ {z_1} \cdot a _ {z_2} \cdot \dots \cdot a_y$ を計算する。 19 | -------------------------------------------------------------------------------- /data_structure/link_cut_tree.vertex_add_path_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/vertex_add_path_sum" 2 | #include "../data_structure/link_cut_tree.hpp" 3 | #include "../monoids/plus.hpp" 4 | #include "../utils/macros.hpp" 5 | #include "../hack/fastio.hpp" 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int main() { 11 | int n = in(); 12 | int q = in(); 13 | 14 | // initialize 15 | link_cut_tree > lct(n); 16 | REP (i, n) { 17 | int64_t a_i = in(); 18 | lct.vertex_set(i, a_i); 19 | } 20 | vector > g(n); 21 | REP (i, n - 1) { 22 | int u = in(); 23 | int v = in(); 24 | g[u].push_back(v); 25 | g[v].push_back(u); 26 | } 27 | vector used(n); 28 | stack stk; 29 | stk.push(0); 30 | used[0] = true; 31 | while (not stk.empty()) { 32 | int u = stk.top(); 33 | stk.pop(); 34 | for (int v : g[u]) if (not used[v]) { 35 | lct.link(v, u); 36 | stk.push(v); 37 | used[v] = true; 38 | } 39 | } 40 | 41 | // answer to queries 42 | while (q --) { 43 | int t = in(); 44 | if (t == 0) { 45 | int p = in(); 46 | int64_t x = in(); 47 | lct.vertex_set(p, lct.vertex_get(p) + x); 48 | } else if (t == 1) { 49 | int u = in(); 50 | int v = in(); 51 | out(lct.path_get(u, v)); 52 | out('\n'); 53 | } 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /data_structure/segment_tree.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | monoid $M = (M, \cdot, 1)$ の要素の列 $a = (a_0, a_1, \dots, a _ {n - 1}) \in M^n$ に対し、次が $O(\log N)$ で処理可能: 4 | 5 | - $\mathtt{point\unicode{95}set}(i, b)$: $a_i \gets b$ と更新する。 6 | - $\mathtt{range\unicode{95}get}(l, r)$: 積 $a_l \cdot a _ {l + 1} \cdot \dots \cdot a _ {r - 1}$ を計算する。 7 | -------------------------------------------------------------------------------- /data_structure/segment_tree.point_add_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | #include "../data_structure/segment_tree.hpp" 3 | #include "../monoids/plus.hpp" 4 | #include "../utils/macros.hpp" 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main() { 12 | int n, q; scanf("%d%d", &n, &q); 13 | vector a(n); 14 | REP (i, n) { 15 | scanf("%lld", &a[i]); 16 | } 17 | segment_tree > segtree(ALL(a)); 18 | while (q --) { 19 | int t, x, y; scanf("%d%d%d", &t, &x, &y); 20 | if (t == 0) { 21 | segtree.point_set(x, segtree.point_get(x) + y); 22 | } else if (t == 1) { 23 | int64_t answer = segtree.range_get(x, y); 24 | printf("%lld\n", answer); 25 | } 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /data_structure/segment_tree.point_set_range_composite.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_set_range_composite" 2 | #include "../data_structure/segment_tree.hpp" 3 | #include "../monoids/linear_function.hpp" 4 | #include "../monoids/dual.hpp" 5 | #include "../modulus/mint.hpp" 6 | #include "../utils/macros.hpp" 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | constexpr int MOD = 998244353; 12 | int main() { 13 | int n, q; scanf("%d%d", &n, &q); 14 | segment_tree > > > segtree(n); 15 | REP (i, n) { 16 | int a, b; scanf("%d%d", &a, &b); 17 | segtree.point_set(i, make_pair(a, b)); 18 | } 19 | while (q --) { 20 | int f, x, y, z; scanf("%d%d%d%d", &f, &x, &y, &z); 21 | if (f == 0) { 22 | segtree.point_set(x, make_pair(y, z)); 23 | } else if (f == 1) { 24 | mint a, b; tie(a, b) = segtree.range_get(x, y); 25 | printf("%d\n", (a * z + b).value); 26 | } 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /data_structure/segment_tree.range_sum_query.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_B" 2 | #include "../data_structure/segment_tree.hpp" 3 | #include "../monoids/plus.hpp" 4 | 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | int n, q; cin >> n >> q; 10 | segment_tree > segtree(n); 11 | while (q --) { 12 | int com, x, y; cin >> com >> x >> y; 13 | -- x; 14 | if (com == 0) { 15 | segtree.point_set(x, segtree.range_get(x, x + 1) + y); 16 | } else if (com == 1) { 17 | cout << segtree.range_get(x, y) << endl; 18 | } 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /data_structure/segment_tree_beats.DSL_2_F.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_F" 2 | #include "../data_structure/segment_tree_beats.hpp" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | #include "../hack/fastio.hpp" 8 | 9 | int main() { 10 | int n = in(); 11 | int q = in(); 12 | 13 | constexpr int64_t initial = (1ull << 31) - 1; 14 | segment_tree_beats beats(n); 15 | beats.range_update(0, n, initial); 16 | 17 | while (q --) { 18 | int ty = in(); 19 | int l = in(); 20 | int r = in(); 21 | ++ r; 22 | if (ty == 0) { 23 | int64_t x = in(); 24 | beats.range_update(l, r, x); 25 | } else { 26 | int64_t min = beats.range_min(l, r); 27 | out(min); 28 | out('\n'); 29 | } 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /data_structure/segment_tree_beats.DSL_2_G.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G" 2 | #include "../data_structure/segment_tree_beats.hpp" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | #include "../hack/fastio.hpp" 8 | 9 | int main() { 10 | int n = in(); 11 | int q = in(); 12 | 13 | segment_tree_beats beats(n); 14 | 15 | while (q --) { 16 | int ty = in(); 17 | int l = in(); 18 | int r = in(); 19 | -- l; 20 | if (ty == 0) { 21 | int64_t x = in(); 22 | beats.range_add(l, r, x); 23 | } else { 24 | int64_t sum = beats.range_sum(l, r); 25 | out(sum); 26 | out('\n'); 27 | } 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /data_structure/segment_tree_beats.DSL_2_H.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_H" 2 | #include "../data_structure/segment_tree_beats.hpp" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | #include "../hack/fastio.hpp" 8 | 9 | int main() { 10 | int n = in(); 11 | int q = in(); 12 | 13 | segment_tree_beats beats(n); 14 | 15 | while (q --) { 16 | int ty = in(); 17 | int l = in(); 18 | int r = in(); 19 | ++ r; 20 | if (ty == 0) { 21 | int64_t x = in(); 22 | beats.range_add(l, r, x); 23 | } else { 24 | int64_t min = beats.range_min(l, r); 25 | out(min); 26 | out('\n'); 27 | } 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /data_structure/segment_tree_beats.DSL_2_I.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_I" 2 | #include "../data_structure/segment_tree_beats.hpp" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | #include "../hack/fastio.hpp" 8 | 9 | int main() { 10 | int n = in(); 11 | int q = in(); 12 | 13 | segment_tree_beats beats(n); 14 | 15 | while (q --) { 16 | int ty = in(); 17 | int l = in(); 18 | int r = in(); 19 | ++ r; 20 | if (ty == 0) { 21 | int64_t x = in(); 22 | beats.range_update(l, r, x); 23 | } else { 24 | int64_t sum = beats.range_sum(l, r); 25 | out(sum); 26 | out('\n'); 27 | } 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /data_structure/segment_tree_beats.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | 整数 $\mathbb{Z} = (\mathbb{Z}, +, 0, \le)$ の要素の列 $a = (a_0, a_1, \dots, a _ {n - 1}) \in \mathbb{Z}^n$ に対し、次が $O((\log N)^2)$ amortized (一部は $O(\log N)$) で処理可能: 4 | 5 | - $\mathtt{range\unicode{95}chmin}(l, r, b)$: それぞれの $i \in \lbrack l, r)$ に対し $a_i \gets \min(a_i, b)$ と更新する。 6 | - $\mathtt{range\unicode{95}chmax}(l, r, b)$: それぞれの $i \in \lbrack l, r)$ に対し $a_i \gets \max(a_i, b)$ と更新する。 7 | - $\mathtt{range\unicode{95}add}(l, r, b)$: それぞれの $i \in \lbrack l, r)$ に対し $a_i \gets a_i + b$ と更新する。 8 | - $\mathtt{range\unicode{95}update}(l, r, b)$: それぞれの $i \in \lbrack l, r)$ に対し $a_i \gets b$ と更新する。 9 | - $\mathtt{range\unicode{95}min}(l, r)$: $\min _ {i \in [l, r)} a_i$ を計算する。 10 | - $\mathtt{range\unicode{95}max}(l, r)$: $\max _ {i \in [l, r)} a_i$ を計算する。 11 | - $\mathtt{range\unicode{95}sum}(l, r)$: $\sum _ {i \in [l, r)} a_i$ を計算する。 12 | 13 | 他にも: 14 | 15 | - $\mathtt{point\unicode{95}set}(i, b)$: $a_i \gets b$ と更新する。 16 | - $\mathtt{point\unicode{95}get}(i)$: 値 $a_i$ を計算する。 17 | -------------------------------------------------------------------------------- /data_structure/segment_tree_beats.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_chmin_chmax_add_range_sum" 2 | #include "../data_structure/segment_tree_beats.hpp" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | #include "../hack/fastio.hpp" 8 | 9 | int main() { 10 | int n = in(); 11 | int q = in(); 12 | 13 | std::vector a(n); 14 | REP (i, n) { 15 | a[i] = in(); 16 | } 17 | segment_tree_beats beats(ALL(a)); 18 | 19 | while (q --) { 20 | int ty = in(); 21 | int l = in(); 22 | int r = in(); 23 | if (ty == 0) { 24 | int64_t b = in(); 25 | beats.range_chmin(l, r, b); 26 | } else if (ty == 1) { 27 | int64_t b = in(); 28 | beats.range_chmax(l, r, b); 29 | } else if (ty == 2) { 30 | int64_t b = in(); 31 | beats.range_add(l, r, b); 32 | } else { 33 | int64_t sum = beats.range_sum(l, r); 34 | out(sum); 35 | out('\n'); 36 | } 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /data_structure/sliding_window_aggregation.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../utils/macros.hpp" 6 | 7 | /** 8 | * @brief Sliding Window Aggregation / 含まれる要素の総和が $O(1)$ で取れる queue (可換とは限らない monoid が乗る) 9 | */ 10 | template 11 | struct sliding_window_aggregation { 12 | typedef typename Monoid::value_type value_type; 13 | Monoid mon; 14 | std::deque data; 15 | int front; 16 | value_type back; 17 | sliding_window_aggregation(const Monoid & mon_ = Monoid()) : mon(mon_) { 18 | front = 0; 19 | back = mon.unit(); 20 | } 21 | /** 22 | * @note O(1) 23 | */ 24 | void push(value_type x) { 25 | data.push_back(x); 26 | back = mon.mult(back, x); 27 | } 28 | /** 29 | * @note amortized O(1) 30 | */ 31 | void pop() { 32 | assert (not data.empty()); 33 | data.pop_front(); 34 | if (front) { 35 | -- front; 36 | } else { 37 | REP_R (i, (int)data.size() - 1) { 38 | data[i] = mon.mult(data[i], data[i + 1]); 39 | } 40 | front = data.size(); 41 | back = mon.unit(); 42 | } 43 | } 44 | /** 45 | * @brief get sum of elements in the queue 46 | * @note O(1) 47 | */ 48 | value_type accumulate() const { 49 | return front ? mon.mult(data.front(), back) : back; 50 | } 51 | bool empty() const { 52 | return data.empty(); 53 | } 54 | std::size_t size() const { 55 | return data.size(); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /data_structure/sliding_window_aggregation.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/queue_operate_all_composite" 2 | #include "../data_structure/sliding_window_aggregation.hpp" 3 | #include "../monoids/linear_function.hpp" 4 | #include "../monoids/dual.hpp" 5 | #include "../modulus/mint.hpp" 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | constexpr int MOD = 998244353; 11 | int main() { 12 | int q; scanf("%d", &q); 13 | sliding_window_aggregation > > > swag; 14 | while (q --) { 15 | int t; scanf("%d", &t); 16 | if (t == 0) { 17 | int a, b; scanf("%d%d", &a, &b); 18 | swag.push(make_pair(a, b)); 19 | } else if (t == 1) { 20 | swag.pop(); 21 | } else if (t == 2) { 22 | int x; scanf("%d", &x); 23 | mint a, b; tie(a, b) = swag.accumulate(); 24 | printf("%d\n", (a * x + b).value); 25 | } 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /data_structure/sparse_table.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | /** 7 | * @brief Sparse Table (idempotent monoid) 8 | * @note the unit is required just for convenience 9 | * @note $O(N \log N)$ space 10 | */ 11 | template 12 | struct sparse_table { 13 | typedef typename IdempotentMonoid::value_type value_type; 14 | std::vector > table; 15 | IdempotentMonoid mon; 16 | sparse_table() = default; 17 | 18 | /** 19 | * @note $O(N \log N)$ time 20 | */ 21 | template 22 | sparse_table(InputIterator first, InputIterator last, const IdempotentMonoid & mon_ = IdempotentMonoid()) 23 | : mon(mon_) { 24 | table.emplace_back(first, last); 25 | int n = table[0].size(); 26 | int log_n = 32 - __builtin_clz(n); 27 | table.resize(log_n, std::vector(n)); 28 | REP (k, log_n - 1) { 29 | REP (i, n) { 30 | table[k + 1][i] = i + (1ll << k) < n ? 31 | mon.mult(table[k][i], table[k][i + (1ll << k)]) : 32 | table[k][i]; 33 | } 34 | } 35 | } 36 | 37 | /** 38 | * @note $O(1)$ 39 | */ 40 | value_type range_get(int l, int r) const { 41 | if (l == r) return mon.unit(); // if there is no unit, remove this line 42 | assert (0 <= l and l < r and r <= (int)table[0].size()); 43 | int k = 31 - __builtin_clz(r - l); // log2 44 | return mon.mult(table[k][l], table[k][r - (1ll << k)]); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /data_structure/sparse_table.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" 2 | #include "../data_structure/sparse_table.hpp" 3 | 4 | #include "../utils/macros.hpp" 5 | #include "../monoids/min.hpp" 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int main() { 11 | // input a sequence 12 | int n, q; scanf("%d%d", &n, &q); 13 | vector a(n); 14 | REP (i, n) { 15 | scanf("%d", &a[i]); 16 | } 17 | 18 | // construct the sparse table 19 | sparse_table > st(ALL(a)); 20 | 21 | // answer to queries 22 | while (q --) { 23 | int l, r; scanf("%d%d", &l, &r); 24 | int answer = st.range_get(l, r); 25 | printf("%d\n", answer); 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /data_structure/sparse_table.yukicoder-1036.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1036" 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | #include "../data_structure/sparse_table.hpp" 6 | #include "../monoids/gcd.hpp" 7 | 8 | long long solve(int n, const std::vector & a) { 9 | sparse_table > table(ALL(a)); 10 | int r = 0; 11 | long long ans = 0; 12 | REP (l, n) { 13 | while (r < n and table.range_get(l, r) != 1) { 14 | ++ r; 15 | } 16 | if (r == n and table.range_get(l, r) != 1) { 17 | break; 18 | } 19 | ans += n - r + 1; 20 | } 21 | return ans; 22 | } 23 | 24 | int main() { 25 | int n; scanf("%d", &n); 26 | std::vector a(n); 27 | REP (i, n) { 28 | scanf("%lld", &a[i]); 29 | } 30 | printf("%lld\n", solve(n, a)); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /data_structure/union_find_tree.aoj.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_A" 2 | #include "../data_structure/union_find_tree.hpp" 3 | #include 4 | 5 | int main() { 6 | int n, q; scanf("%d%d", &n, &q); 7 | union_find_tree uft(n); 8 | while (q --) { 9 | int com, x, y; scanf("%d%d%d", &com, &x, &y); 10 | if (com == 0) { 11 | uft.unite_trees(x, y); 12 | } else if (com == 1) { 13 | bool answer = uft.is_same(x, y); 14 | printf("%d\n", (int)answer); 15 | } 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /data_structure/union_find_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * @brief Union-Find Tree 6 | * @docs data_structure/union_find_tree.md 7 | * @note union-by-size + path-compression 8 | */ 9 | struct union_find_tree { 10 | std::vector data; 11 | union_find_tree() = default; 12 | explicit union_find_tree(std::size_t n) : data(n, -1) {} 13 | bool is_root(int i) { return data[i] < 0; } 14 | int find_root(int i) { return is_root(i) ? i : (data[i] = find_root(data[i])); } 15 | int tree_size(int i) { return - data[find_root(i)]; } 16 | int unite_trees(int i, int j) { 17 | i = find_root(i); j = find_root(j); 18 | if (i != j) { 19 | if (tree_size(i) < tree_size(j)) std::swap(i, j); 20 | data[i] += data[j]; 21 | data[j] = i; 22 | } 23 | return i; 24 | } 25 | bool is_same(int i, int j) { return find_root(i) == find_root(j); } 26 | }; 27 | -------------------------------------------------------------------------------- /data_structure/union_find_tree.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | 頂点数 $N$ で辺数 $0$ の無向グラフ $G = (V, E)$ に対し、次が $O(\alpha(N))$ amortized (ただし $\alpha$ は Ackermann 関数の逆関数) で処理可能。 4 | 5 | - $\mathtt{unite\unicode{95}trees}(u, v)$: 頂点 $u, v$ 間に辺を追加する。 6 | - $u, v$ 間の辺は無向であることに注意 7 | - $\mathtt{find\unicode{95}root}(v)$: 頂点 $v$ の所属する連結成分の代表元を取得する。 8 | - $\mathtt{is\unicode{95}same}(u, v)$: 頂点 $u, v$ が同じ連結成分に所属するかを判定する。 9 | - $\mathtt{tree\unicode{95}size}(v)$: 頂点 $v$ の所属する連結成分の要素数を取得する。 10 | -------------------------------------------------------------------------------- /data_structure/union_find_tree.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/unionfind" 2 | #include "../data_structure/union_find_tree.hpp" 3 | #include 4 | 5 | int main() { 6 | int n, q; scanf("%d%d", &n, &q); 7 | union_find_tree uft(n); 8 | while (q --) { 9 | int t, u, v; scanf("%d%d%d", &t, &u, &v); 10 | if (t == 0) { 11 | uft.unite_trees(u, v); 12 | } else if (t == 1) { 13 | bool answer = uft.is_same(u, v); 14 | printf("%d\n", (int)answer); 15 | } 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /data_structure/union_find_tree_with_monoid.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * @brief a disjoint set structure with monoid 6 | * @note union-by-size + path-compression 7 | */ 8 | template 9 | struct union_find_tree_with_monoid { 10 | typedef typename Monoid::value_type value_type; 11 | const Monoid mon; 12 | std::vector data; 13 | std::vector value; 14 | 15 | union_find_tree_with_monoid() = default; 16 | union_find_tree_with_monoid(std::size_t n, Monoid const & mon_ = Monoid()) : mon(mon_), data(n, -1), value(n, mon.unit()) {} 17 | bool is_root(int i) { return data[i] < 0; } 18 | int find_root(int i) { return is_root(i) ? i : (data[i] = find_root(data[i])); } 19 | int tree_size(int i) { return - data[find_root(i)]; } 20 | int unite_trees(int i, int j) { 21 | i = find_root(i); j = find_root(j); 22 | if (i != j) { 23 | if (tree_size(i) < tree_size(j)) std::swap(i, j); 24 | data[i] += data[j]; 25 | data[j] = i; 26 | value[i] = mon.mult(value[i], value[j]); 27 | } 28 | return i; 29 | } 30 | bool is_same(int i, int j) { return find_root(i) == find_root(j); } 31 | value_type get_value(int i) { return value[find_root(i)]; } 32 | void set_value(int i, value_type z) { value[find_root(i)] = z; } 33 | }; 34 | -------------------------------------------------------------------------------- /data_structure/wavelet_matrix.aoj2674.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2674" 2 | #include "../data_structure/wavelet_matrix.hpp" 3 | #include "../utils/macros.hpp" 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | constexpr int BITS = 30; 10 | constexpr int MIN_X = -1e8; 11 | constexpr int MAX_X = 1e8; 12 | 13 | // read a sequence 14 | int d; scanf("%d", &d); 15 | vector x(d); 16 | REP (i, d) { 17 | scanf("%d", &x[i]); 18 | x[i] -= MIN_X; 19 | } 20 | 21 | // construct a wavelet matrix 22 | wavelet_matrix wm(x); 23 | 24 | // answer to queries 25 | int q; scanf("%d", &q); 26 | while (q --) { 27 | int l, r, e; scanf("%d%d%d", &l, &r, &e); 28 | -- l; 29 | int a = min(x[l], x[r - 1]); 30 | int b = max(x[l], x[r - 1]); 31 | int cnt = 0; 32 | cnt += wm.range_frequency(l, r, 0, max(0, a - e)); 33 | cnt += wm.range_frequency(l, r, min(MAX_X - MIN_X + 1, b + e + 1), MAX_X - MIN_X + 1); 34 | printf("%d\n", cnt); 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /data_structure/wavelet_matrix.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | 3 | 完備辞書を $K$ 本ならべて $2^K$ 未満の自然数に対応させたような静的データ構造。 4 | 5 | ## Operations 6 | 7 | ある固定された自然数 $K$ と $2^K$ 未満の自然数の列 $a = (a_0, a_1, \dots, a _ {n - 1}) \in (2^K)^N$ に対し、次が $O(K)$ で処理可能: 8 | 9 | - $\mathtt{rank}(b, l, r)$: 区間 $\lbrack l, r)$ 中の値 $b$ の出現回数 $$\unicode{35} \lbrace i \in \lbrack l, r) \mid a_i = b \rbrace$$ を計算する。 10 | - $\mathtt{select}(b, k, l)$: 位置 $l$ 以降で $k \ge 0$ 番目に出現する値 $b$ の位置 $i$ (つまり $i \ge l$ かつ $a_i = b$ かつ $$\unicode{35} \lbrace j \in \lbrack l, i) \mid a_j = b \rbrace = k$$ を満たす $i$) を計算する。 11 | - ただし今回の実装では完備辞書側の妥協の結果 $O(K \log N)$ になっている 12 | - $\mathtt{access}(i)$: 値 $a_i$ を計算する。 13 | - $\mathtt{quantile}(k, l, r)$: 区間 $\lbrack l, r)$ 内で $k \ge 0$ 番目に小さい要素 $a_i$ (つまり $$\unicode{35} \lbrace j \in \lbrack l, r) \mid (a_j, j) \lt (a_i, i) \rbrace = k$$ を満たす $i$) を計算する。 14 | - $\mathtt{range\unicode{95}frequency}(l, r, b_l, b_r)$: 区間 $\lbrack l, r)$ 内における $b_l$ 以上 $b_r$ 未満の要素の数 $$\unicode{35} \lbrace i \in \lbrack l, r) \mid a_i \in \lbrack b_l, b_r) \rbrace$$ を計算する。 15 | -------------------------------------------------------------------------------- /data_structure/wavelet_matrix.range_kth_smallest.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_kth_smallest" 2 | #include "../data_structure/wavelet_matrix.hpp" 3 | #include "../utils/macros.hpp" 4 | #include "../hack/fastio.hpp" 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | // input 10 | int n = in(); 11 | int q = in(); 12 | vector a(n); 13 | REP (i, n) { 14 | a[i] = in(); 15 | } 16 | 17 | // construct 18 | wavelet_matrix<30> wm(a); 19 | 20 | // output 21 | while (q --) { 22 | int l = in(); 23 | int r = in(); 24 | int k = in(); 25 | int32_t b = wm.quantile(k, l, r); 26 | out(b); 27 | out('\n'); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat < ~/.vimrc 4 | syntax on 5 | set smartindent 6 | set tabstop=4 7 | set shiftwidth=4 8 | set expandtab 9 | set relativenumber 10 | EOF 11 | 12 | setxkbmap -option ctrl:swapcaps 13 | 14 | alias e=vim 15 | alias cxx='$CXX -std=c++14 -Wall -O2' 16 | alias cxxo='$CXX -std=c++14 -Wall -O3 -mtune=native -march=native' 17 | alias cxxg='$CXX -std=c++14 -Wall -g -fsanitize=undefined -D_GLIBCXX_DEBUG' 18 | 19 | judge() { 20 | for f in test/*.in ; do 21 | echo $f 22 | diff <(./a.out < $f) ${f%.in}.out 23 | done 24 | } 25 | print() { 26 | for x in {A..Z} ; do 27 | url=http://255.255.255.255/${x}_ja.html 28 | if [[ $(curl -s $url -o /dev/null -w '%{http_code}') = 200 ]] ; then 29 | google-chrome --headless --disable-gpu --print-to-pdf $url 30 | lpr output.pdf 31 | fi 32 | done 33 | } 34 | -------------------------------------------------------------------------------- /graph/bellman_ford.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../utils/macros.hpp" 10 | 11 | /** 12 | * @brief Bellman-Ford algorithm 13 | * @note O(V E) 14 | * @arg g is a digraph with possibly negative cost edges 15 | * @note INT64_MIN for negative loops 16 | * @note INT64_MAX for unreachable nodes 17 | */ 18 | std::vector bellman_ford_shortest_path(int root, std::vector > > const & g) { 19 | assert (not g.empty()); 20 | int n = g.size(); 21 | std::vector dist(n, INT64_MAX); 22 | 23 | // update n - 1 times 24 | dist[root] = 0; 25 | REP (iteration, n - 1) { 26 | REP (i, n) if (dist[i] != INT64_MAX) { 27 | for (auto edge : g[i]) { 28 | int j; int64_t cost; std::tie(j, cost) = edge; 29 | dist[j] = std::min(dist[j], dist[i] + cost); 30 | } 31 | } 32 | } 33 | 34 | // propagate effects of negative cycles 35 | std::stack stk; 36 | REP (i, n) if (dist[i] != INT64_MAX) { 37 | stk.push(i); 38 | } 39 | while (not stk.empty()) { 40 | int i = stk.top(); 41 | stk.pop(); 42 | for (auto edge : g[i]) { 43 | int j; int64_t cost; std::tie(j, cost) = edge; 44 | if (dist[j] != INT64_MIN) { 45 | if (dist[i] == INT64_MIN or dist[i] + cost < dist[j]) { 46 | dist[j] = INT64_MIN; 47 | stk.push(j); 48 | } 49 | } 50 | } 51 | } 52 | 53 | return dist; 54 | } 55 | -------------------------------------------------------------------------------- /graph/bellman_ford.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_B" 2 | #ifdef USE_SPFA 3 | #include "../graph/shortest_path_faster_algorithm.hpp" 4 | auto BELLMAN_FORD = shortest_path_faster_algorithm; 5 | #else 6 | #include "../graph/bellman_ford.hpp" 7 | auto BELLMAN_FORD = bellman_ford_shortest_path; 8 | #endif 9 | 10 | #include 11 | #include 12 | #include "../utils/macros.hpp" 13 | using namespace std; 14 | 15 | int main() { 16 | // input 17 | int v, e, root; cin >> v >> e >> root; 18 | vector > > g(v); 19 | REP (j, e) { 20 | int s, t, dist; cin >> s >> t >> dist; 21 | g[s].emplace_back(t, dist); 22 | } 23 | 24 | // solve 25 | auto dist = BELLMAN_FORD(root, g); 26 | 27 | // output 28 | if (count(ALL(dist), LLONG_MIN)) { 29 | cout << "NEGATIVE CYCLE" << endl; 30 | } else { 31 | REP (i, v) { 32 | if (dist[i] == LLONG_MAX) { 33 | cout << "INF" << endl; 34 | } else { 35 | cout << dist[i] << endl; 36 | } 37 | } 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /graph/cartesian_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | /** 7 | * @brief Cartesian tree ($O(n)$) 8 | * @note the smallest value is the root 9 | * @note if a is not distinct, the way for tie-break is undefined 10 | * @return the binary tree as the list of parents 11 | */ 12 | template > 13 | std::vector construct_cartesian_tree(const std::vector & a, const Comparator & cmp = Comparator()) { 14 | int n = a.size(); 15 | std::vector parent(n, -1); 16 | REP3 (i, 1, n) { 17 | int p = i - 1; // parent of i 18 | int l = -1; // left child of i 19 | while (p != -1 and cmp(a[i], a[p])) { 20 | int pp = parent[p]; // parent of parent of i 21 | if (l != -1) { 22 | parent[l] = p; 23 | } 24 | parent[p] = i; 25 | l = p; 26 | p = pp; 27 | } 28 | parent[i] = p; 29 | } 30 | return parent; 31 | } 32 | -------------------------------------------------------------------------------- /graph/cartesian_tree.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/cartesian_tree" 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | #include "../graph/cartesian_tree.hpp" 6 | 7 | int main(){ 8 | // input 9 | int n; scanf("%d", &n); 10 | std::vector a(n); 11 | REP (i, n) { 12 | scanf("%d", &a[i]); 13 | } 14 | 15 | // solve 16 | std::vector p = construct_cartesian_tree(a); 17 | 18 | // output 19 | REP (i, n) { 20 | printf("%d%c", p[i] == -1 ? i : p[i], i + 1 < n ? ' ' : '\n'); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /graph/cartesian_tree.yukicoder-1031.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1031" 2 | #include "../utils/macros.hpp" 3 | #include "../graph/cartesian_tree.hpp" 4 | #include "../graph/format.hpp" 5 | #include "../utils/left_to_right_maxima.hpp" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | using namespace std; 13 | 14 | int64_t solve1(int n, const vector & p) { 15 | // prepare a data structure for the sequence 16 | auto f = left_to_right_maxima::construct(ALL(p)); 17 | 18 | // construct the Cartesian tree 19 | vector parent = construct_cartesian_tree(p); 20 | vector > children; int root; tie(children, root) = children_from_parent(parent); 21 | 22 | // fold the Cartesian tree 23 | int64_t ans = 0; 24 | auto go = [&](auto && go, int l, int m, int r) -> void { 25 | if (l == r) { 26 | return; 27 | } 28 | ans += f(m + 1, r); 29 | for (int x : children[m]) { 30 | if (x < m) { 31 | go(go, l, x, m); 32 | } else { 33 | go(go, m + 1, x, r); 34 | } 35 | } 36 | }; 37 | go(go, 0, root, n); 38 | return ans; 39 | } 40 | 41 | int64_t solve(int n, vector p) { 42 | int64_t ans = solve1(n, p); 43 | reverse(ALL(p)); 44 | return ans + solve1(n, p); 45 | } 46 | 47 | int main() { 48 | int n; scanf("%d", &n); 49 | vector p(n); 50 | REP (i, n) { 51 | scanf("%d", &p[i]); 52 | } 53 | long long ans = solve(n, p); 54 | printf("%lld\n", ans); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /graph/connected_components.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | /** 7 | * @param g is an undirected graph 8 | */ 9 | int count_connected_components(const std::vector > & g) { 10 | int n = g.size(); 11 | int cnt = 0; 12 | std::vector used(n); 13 | std::stack stk; 14 | REP (z, n) if (not used[z]) { 15 | ++ cnt; 16 | used[z] = true; 17 | stk.push(z); 18 | while (not stk.empty()) { 19 | int x = stk.top(); 20 | stk.pop(); 21 | for (int y : g[x]) if (not used[y]) { 22 | used[y] = true; 23 | stk.push(y); 24 | } 25 | } 26 | } 27 | return cnt; 28 | } 29 | 30 | /** 31 | * @param g is an undirected graph 32 | */ 33 | bool is_connected_graph(const std::vector > & g) { 34 | return count_connected_components(g) == 1; 35 | } 36 | -------------------------------------------------------------------------------- /graph/diameter_of_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * @brief get the diameter of a tree / 木の直径 8 | * @note $O(N)$ 9 | * @return (depth, vertex) 10 | * @sa http://techtipshoge.blogspot.jp/2016/09/blog-post.html 11 | */ 12 | std::pair get_eccentricity(int root, const std::vector >& tree) { 13 | std::pair result = { -1, -1 }; // (depth, vertex) 14 | auto dfs = [&](auto&& dfs, int x, int parent, int depth) -> void { 15 | result = std::max(result, std::make_pair(depth, x)); 16 | for (int y : tree[x]) if (y != parent) { 17 | dfs(dfs, y, x, depth + 1); 18 | } 19 | }; 20 | dfs(dfs, root, -1, 0); 21 | return result; 22 | } 23 | 24 | int get_diameter(const std::vector >& tree) { 25 | return get_eccentricity(get_eccentricity(0, tree).second, tree).first; 26 | } 27 | -------------------------------------------------------------------------------- /graph/dijkstra.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /** 9 | * @brief Dijkstra ($O((E + V) \log V)$) 10 | */ 11 | template 12 | std::vector dijkstra(std::vector > > const & g, int root) { 13 | std::vector dist(g.size(), std::numeric_limits::max()); 14 | std::priority_queue > que; 15 | dist[root] = 0; 16 | que.emplace(- dist[root], root); 17 | while (not que.empty()) { 18 | T dist_x; int x; std::tie(dist_x, x) = que.top(); que.pop(); 19 | if (dist[x] < - dist_x) continue; 20 | for (auto it : g[x]) { 21 | int y; T cost; std::tie(y, cost) = it; 22 | if (- dist_x + cost < dist[y]) { 23 | dist[y] = - dist_x + cost; 24 | que.emplace(dist_x - cost, y); 25 | } 26 | } 27 | } 28 | return dist; 29 | } 30 | -------------------------------------------------------------------------------- /graph/dijkstra.yukicoder-1065.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1065" 2 | #define ERROR 1e-4 3 | #include 4 | #include "../utils/macros.hpp" 5 | #include "../graph/dijkstra.hpp" 6 | using namespace std; 7 | 8 | 9 | int main() { 10 | // input 11 | int n, m; scanf("%d%d", &n, &m); 12 | int start, goal; scanf("%d%d", &start, &goal); 13 | -- start; 14 | -- goal; 15 | vector x(n), y(n); 16 | REP (i, n) { 17 | scanf("%lld%lld", &x[i], &y[i]); 18 | } 19 | vector > > g(n); 20 | REP (i, m) { 21 | int p, q; cin >> p >> q; 22 | -- p; 23 | -- q; 24 | double cost = sqrt(pow(x[p] - x[q], 2) + pow(y[p] - y[q], 2)); 25 | g[p].emplace_back(q, cost); 26 | g[q].emplace_back(p, cost); 27 | } 28 | 29 | // solve 30 | auto dist = dijkstra(g, start); 31 | 32 | // output 33 | printf("%.12lf\n", dist[goal]); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /graph/euler_tour_preorder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | /** 6 | * @brief Euler Tour (preorder) 7 | * @arg g must be a rooted tree, directed or undirected 8 | */ 9 | void do_euler_tour_preorder(std::vector > const & g, int root, std::vector & tour, std::vector & left, std::vector & right) { 10 | int n = g.size(); 11 | tour.clear(); 12 | left.assign(n, -1); 13 | right.assign(n, -1); 14 | std::function go = [&](int x, int parent) { 15 | left[x] = tour.size(); 16 | tour.push_back(x); 17 | for (int y : g[x]) if (y != parent) { 18 | go(y, x); 19 | } 20 | right[x] = tour.size(); 21 | }; 22 | go(root, -1); 23 | } 24 | -------------------------------------------------------------------------------- /graph/format.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../utils/macros.hpp" 6 | 7 | std::pair >, int> children_from_parent(const std::vector & parent) { 8 | int n = parent.size(); 9 | std::vector > children(n); 10 | int root = -1; 11 | REP (x, n) { 12 | if (parent[x] == -1) { 13 | assert (root == -1); 14 | root = x; 15 | } else { 16 | children[parent[x]].push_back(x); 17 | } 18 | } 19 | assert (root != -1); 20 | return std::make_pair(children, root); 21 | } 22 | 23 | std::vector > adjacent_list_from_children(const std::vector > & children) { 24 | int n = children.size(); 25 | std::vector > g(n); 26 | REP (x, n) { 27 | for (int y : children[x]) { 28 | g[x].push_back(y); 29 | g[y].push_back(x); 30 | } 31 | } 32 | return g; 33 | } 34 | -------------------------------------------------------------------------------- /graph/functional_graph.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * @brief Namori cycle / なもり閉路 9 | * @param g a simple connected undirected graph with |E| = |V| 10 | */ 11 | std::deque get_namori_cycle(const std::vector >& g) { 12 | int n = g.size(); 13 | { // check the namori-ty 14 | int m = 0; 15 | REP (i, n) { 16 | m += g[i].size(); 17 | } 18 | assert (m == 2 * n); 19 | } 20 | 21 | std::deque stk; 22 | std::vector used(n); 23 | auto go = [&](auto&& go, int i, int parent) -> int { 24 | if (used[i]) return i; 25 | stk.push_back(i); 26 | used[i] = true; 27 | for (int j : g[i]) if (j != parent) { 28 | int k = go(go, j, i); 29 | if (k != -1) return k; 30 | } 31 | assert (stk.back() == i); 32 | stk.pop_back(); 33 | used[i] = false; 34 | return -1; 35 | }; 36 | int i = go(go, 0, -1); 37 | assert (i != -1); // fails if the graph is not simple 38 | while (stk.front() != i) { 39 | stk.pop_front(); 40 | } 41 | return stk; 42 | } 43 | -------------------------------------------------------------------------------- /graph/functional_graph.yuki1254.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1254" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../utils/macros.hpp" 8 | #include "../graph/functional_graph.hpp" 9 | using namespace std; 10 | 11 | vector solve(int n, const vector >& edges) { 12 | vector > g(n); 13 | map, int> lookup; 14 | REP (i, edges.size()) { 15 | auto [a, b] = edges[i]; 16 | g[a].push_back(b); 17 | g[b].push_back(a); 18 | lookup[make_pair(a, b)] = i; 19 | lookup[make_pair(b, a)] = i; 20 | } 21 | 22 | auto cycle = get_namori_cycle(g); 23 | vector ans; 24 | REP (i, cycle.size()) { 25 | int a = cycle[i]; 26 | int b = cycle[(i + 1) % cycle.size()]; 27 | ans.push_back(lookup[make_pair(a, b)]); 28 | } 29 | sort(ALL(ans)); 30 | return ans; 31 | } 32 | 33 | int main() { 34 | int n; scanf("%d", &n); 35 | vector > edges(n); 36 | REP (i, n) { 37 | int a, b; scanf("%d%d", &a, &b); 38 | -- a; 39 | -- b; 40 | edges[i] = make_pair(a, b); 41 | } 42 | vector ans = solve(n, edges); 43 | printf("%d\n", (int)ans.size()); 44 | REP (i, ans.size()) { 45 | printf("%d%c", ans[i] + 1, i + 1 < ans.size() ? ' ' : '\n'); 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /graph/is_connected_graph.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | bool is_connected_graph(const std::vector> &g) { 6 | int n = g.size(); 7 | std::vector used(n); 8 | auto go = [&](auto &&go, int x) -> void { 9 | used[x] = true; 10 | for (int y : g[x]) { 11 | if (not used[y]) { 12 | go(go, y); 13 | } 14 | } 15 | }; 16 | go(go, 0); 17 | return std::find(ALL(used), false) == used.end(); 18 | } 19 | -------------------------------------------------------------------------------- /graph/is_simple_graph.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | bool is_simple_graph(const std::vector> &g) { 7 | int n = g.size(); 8 | REP (x, n) { 9 | std::set used; 10 | for (int y : g[x]) { 11 | if (y == x or used.count(y)) { 12 | return false; 13 | } 14 | used.insert(y); 15 | } 16 | } 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /graph/kruskal.aoj.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_12_A" 2 | #include "../graph/kruskal.hpp" 3 | 4 | #include "../utils/macros.hpp" 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int main() { 10 | // input 11 | int n; scanf("%d", &n); 12 | vector > edges; 13 | REP (x, n) { 14 | REP (y, n) { 15 | long long a; scanf("%lld", &a); 16 | if (a != -1) { 17 | edges.emplace_back(x, y, a); 18 | } 19 | } 20 | } 21 | 22 | // solve 23 | vector mst = compute_minimum_spanning_tree(n, edges); 24 | long long answer = 0; 25 | for (int i : mst) { 26 | answer += get<2>(edges[i]); 27 | } 28 | 29 | // output 30 | printf("%lld\n", answer); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /graph/kruskal.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../data_structure/union_find_tree.hpp" 3 | #include "../utils/macros.hpp" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /** 10 | * @brief minimum spanning tree / 最小全域木 (Kruskal's method) 11 | * @note $O(E \log E)$ 12 | * @note it becomes a forest if the given graph is not connected 13 | * @return a list of indices of edges 14 | */ 15 | template 16 | std::vector compute_minimum_spanning_tree(int n, std::vector > edges) { 17 | std::vector order(edges.size()); 18 | std::iota(ALL(order), 0); 19 | std::sort(ALL(order), [&](int i, int j) { 20 | return std::make_pair(std::get<2>(edges[i]), i) < std::make_pair(std::get<2>(edges[j]), j); 21 | }); 22 | std::vector tree; 23 | union_find_tree uft(n); 24 | for (int i : order) { 25 | int x = std::get<0>(edges[i]); 26 | int y = std::get<1>(edges[i]); 27 | if (not uft.is_same(x, y)) { 28 | uft.unite_trees(x, y); 29 | tree.push_back(i); 30 | } 31 | } 32 | return tree; 33 | } 34 | -------------------------------------------------------------------------------- /graph/lowest_common_ancestor.aoj.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_C" 2 | 3 | #include "../graph/lowest_common_ancestor.hpp" 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | // read a tree 10 | int n; scanf("%d", &n); 11 | vector > g(n); 12 | REP (i, n) { 13 | int k; scanf("%d", &k); 14 | REP (j, k) { 15 | int c; scanf("%d", &c); 16 | g[i].push_back(c); 17 | g[c].push_back(i); 18 | } 19 | } 20 | 21 | // construct the LCA 22 | constexpr int root = 0; 23 | lowest_common_ancestor lca(root, g); 24 | 25 | // answer to queries 26 | int q; scanf("%d", &q); 27 | while (q --) { 28 | int u, v; scanf("%d%d", &u, &v); 29 | printf("%d\n", lca(u, v)); 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /graph/lowest_common_ancestor.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/lca" 2 | #include "../graph/lowest_common_ancestor.hpp" 3 | 4 | #include "../utils/macros.hpp" 5 | #include "../hack/stack_pivot.hpp" 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int moin() { 11 | // read a tree 12 | int n, q; scanf("%d%d", &n, &q); 13 | vector > g(n); 14 | REP (i, n - 1) { 15 | int p; scanf("%d", &p); 16 | g[i + 1].push_back(p); 17 | g[p].push_back(i + 1); 18 | } 19 | 20 | // construct the LCA 21 | constexpr int root = 0; 22 | lowest_common_ancestor lca(root, g); 23 | 24 | // answer to queries 25 | while (q --) { 26 | int u, v; scanf("%d%d", &u, &v); 27 | printf("%d\n", lca(u, v)); 28 | } 29 | return 0; 30 | } 31 | 32 | STACK_PIVOT_MAIN(moin) 33 | -------------------------------------------------------------------------------- /graph/quotient_graph.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../graph/transpose_graph.hpp" 4 | #include "../utils/macros.hpp" 5 | 6 | /** 7 | * @param g is an adjacent list of a digraph 8 | * @param size is the size of equivalence classes 9 | * @param component_of is the map from original vertices to equivalence classes 10 | * @note $O(V + E)$ 11 | * @see https://en.wikipedia.org/wiki/Quotient_graph 12 | */ 13 | std::vector > make_quotient_graph(const std::vector > & g, int size, const std::vector & component_of) { 14 | int n = g.size(); 15 | std::vector > h(size); 16 | REP (i, n) for (int j : g[i]) { 17 | if (component_of[i] != component_of[j]) { 18 | h[component_of[i]].push_back(component_of[j]); 19 | } 20 | } 21 | REP (k, size) { 22 | std::sort(ALL(h[k])); 23 | h[k].erase(std::unique(ALL(h[k])), h[k].end()); 24 | } 25 | return h; 26 | } 27 | -------------------------------------------------------------------------------- /graph/shortest_path_faster_algorithm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../utils/macros.hpp" 10 | 11 | /** 12 | * @brief Shortest Path Faster Algorithm 13 | * @note the interface is same to one of Bellman Ford 14 | */ 15 | std::vector shortest_path_faster_algorithm(int root, std::vector > > const & g) { 16 | assert (not g.empty()); 17 | int n = g.size(); 18 | std::vector dist(n, INT64_MAX); 19 | std::deque cur, nxt; 20 | std::vector pushed(n); 21 | dist[root] = 0; 22 | nxt.push_back(root); 23 | pushed[root] = true; 24 | 25 | REP (iteration, 2 * n - 2) { 26 | cur.swap(nxt); 27 | while (not cur.empty()) { 28 | int x = cur.front(); 29 | cur.pop_front(); 30 | pushed[x] = false; 31 | for (const auto & edge : g[x]) { 32 | int y; int64_t cost; std::tie(y, cost) = edge; 33 | if ((dist[x] == INT64_MIN ? INT64_MIN : dist[x] + cost) < dist[y]) { 34 | dist[y] = (iteration >= n - 1 ? INT64_MIN : dist[x] + cost); 35 | if (not pushed[y]) { 36 | if (not nxt.empty() and dist[y] < dist[nxt.front()]) { 37 | // Small Label First 38 | nxt.push_front(y); 39 | } else { 40 | nxt.push_back(y); 41 | } 42 | pushed[y] = true; 43 | } 44 | } 45 | } 46 | } 47 | if (nxt.empty()) break; 48 | } 49 | 50 | return dist; 51 | } 52 | -------------------------------------------------------------------------------- /graph/strongly_connected_components.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../graph/transpose_graph.hpp" 6 | #include "../utils/macros.hpp" 7 | 8 | /** 9 | * @brief strongly connected components decomposition, Kosaraju's algorithm / 強連結成分分解 10 | * @return the pair (the number k of components, the function from vertices of g to components) 11 | * @param g is an adjacent list of a digraph 12 | * @param g_rev is the transpose graph of g 13 | * @note $O(V + E)$ 14 | */ 15 | std::pair > decompose_to_strongly_connected_components(const std::vector > & g, const std::vector > & g_rev) { 16 | int n = g.size(); 17 | std::vector acc; { 18 | std::vector used(n); 19 | std::function dfs = [&](int i) { 20 | used[i] = true; 21 | for (int j : g[i]) if (not used[j]) dfs(j); 22 | acc.push_back(i); 23 | }; 24 | REP (i,n) if (not used[i]) dfs(i); 25 | reverse(ALL(acc)); 26 | } 27 | int size = 0; 28 | std::vector component_of(n); { 29 | std::vector used(n); 30 | std::function rdfs = [&](int i) { 31 | used[i] = true; 32 | component_of[i] = size; 33 | for (int j : g_rev[i]) if (not used[j]) rdfs(j); 34 | }; 35 | for (int i : acc) if (not used[i]) { 36 | rdfs(i); 37 | ++ size; 38 | } 39 | } 40 | return { size, move(component_of) }; 41 | } 42 | 43 | std::pair > decompose_to_strongly_connected_components(const std::vector > & g) { 44 | return decompose_to_strongly_connected_components(g, make_transpose_graph(g)); 45 | } 46 | -------------------------------------------------------------------------------- /graph/strongly_connected_components.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/scc" 2 | #include "../graph/strongly_connected_components.hpp" 3 | #include "../graph/quotient_graph.hpp" 4 | #include "../graph/topological_sort.hpp" 5 | #include "../utils/macros.hpp" 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main() { 12 | // input 13 | int n, m; scanf("%d%d", &n, &m); 14 | vector > g(n); 15 | REP (i, m) { 16 | int a, b; scanf("%d%d", &a, &b); 17 | g[a].push_back(b); 18 | } 19 | 20 | // solve 21 | int size; vector component_of; tie(size, component_of) = decompose_to_strongly_connected_components(g); 22 | vector > component(size); 23 | REP (i, n) { 24 | component[component_of[i]].push_back(i); 25 | } 26 | vector > h = make_quotient_graph(g, size, component_of); 27 | vector order = topological_sort(h); 28 | assert (order.size() == size); 29 | 30 | // output 31 | printf("%d\n", size); 32 | for (int a : order) { 33 | printf("%d", (int)component[a].size()); 34 | for (int i : component[a]) { 35 | printf(" %d", i); 36 | } 37 | printf("\n"); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /graph/subtree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | struct subtree_info_t { 6 | int parent; // in the entire tree 7 | int depth; // in the entire tree 8 | int size; // of the subtree 9 | int height; // of the subtree 10 | }; 11 | 12 | /** 13 | * @brief subtree info / それぞれの部分木の size とか height とかをまとめて求めておいてくれるやつ 14 | * @arg g must be a tree 15 | * @note O(n) time 16 | * @note O(n) space on heap 17 | */ 18 | std::vector prepare_subtree_info(std::vector > const & g, int root) { 19 | int n = g.size(); 20 | std::vector info(n, (subtree_info_t) { -1, -1, -1, -1 }); 21 | std::vector topological(n); 22 | topological[0] = root; 23 | info[root].parent = root; 24 | info[root].depth = 0; 25 | int r = 1; 26 | for (int l = 0; l < r; ++ l) { 27 | int i = topological[l]; 28 | for (int j : g[i]) if (j != info[i].parent) { 29 | topological[r ++] = j; 30 | info[j].parent = i; 31 | info[j].depth = info[i].depth + 1; 32 | } 33 | } 34 | while ((-- r) >= 0) { 35 | int i = topological[r]; 36 | info[i].size = 1; 37 | info[i].height = 0; 38 | for (int j : g[i]) if (j != info[i].parent) { 39 | info[i].size += info[j].size; 40 | info[i].height = std::max(info[i].height, info[j].height + 1); 41 | } 42 | } 43 | info[root].parent = -1; 44 | return info; 45 | } 46 | -------------------------------------------------------------------------------- /graph/topological_sort.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../utils/macros.hpp" 6 | 7 | /** 8 | * @brief topological sort 9 | * @return a list of vertices which sorted topologically 10 | * @note the empty list is returned if cycles exist 11 | * @note $O(V + E)$ 12 | */ 13 | std::vector topological_sort(const std::vector > & g) { 14 | int n = g.size(); 15 | std::vector order; 16 | std::vector used(n); 17 | std::function go = [&](int i) { 18 | used[i] = 1; // in stack 19 | for (int j : g[i]) { 20 | if (used[j] == 1) return true; 21 | if (not used[j]) { 22 | if (go(j)) return true; 23 | } 24 | } 25 | used[i] = 2; // completely used 26 | order.push_back(i); 27 | return false; 28 | }; 29 | REP (i, n) if (not used[i]) { 30 | if (go(i)) return std::vector(); 31 | } 32 | std::reverse(ALL(order)); 33 | return order; 34 | } 35 | -------------------------------------------------------------------------------- /graph/transpose_graph.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../utils/macros.hpp" 4 | 5 | /** 6 | * @param g is an adjacent list of a digraph 7 | * @note $O(V + E)$ 8 | * @see https://en.wikipedia.org/wiki/Transpose_graph 9 | */ 10 | std::vector > make_transpose_graph(std::vector > const & g) { 11 | int n = g.size(); 12 | std::vector > h(n); 13 | REP (i, n) { 14 | for (int j : g[i]) { 15 | h[j].push_back(i); 16 | } 17 | } 18 | return h; 19 | } 20 | -------------------------------------------------------------------------------- /graph/tree_decomposition.md: -------------------------------------------------------------------------------- 1 | ## 説明 2 | 3 | ある (根付きではなく) 頂点に集合重みの付いた木 $T = (I, F; X)$ が無向グラフ $G = (V, E)$ の a tree decomposition であるとは、次をすべて満たすことをいう。 4 | 5 | 1. 頂点 $i \in I$ の重みは $G$ の頂点の部分集合である $X_i \subseteq V$ 6 | 1. 任意の辺 $(u, v) \in E$ に対し、ある $i \in I$ が存在し、$u \in X_i$ かつ $v \in X_i$ である 7 | 1. 任意の頂点 $v \in V$ に対し、頂点の集合 $\lbrace i \in I \mid v \in X_i \rbrace$ は $T$ 上で連結 8 | 9 | a tree decomposition $T = (I, F; X)$ の幅とは、その頂点の要素数の最大値 $\max \lbrace \unicode{35} X \mid X \in I \rbrace$ のことをいう。 10 | 無向グラフの木幅とは、その tree decompositions の幅の最大値のことをいう。 11 | 12 | 木幅 $t = 2$ が分かっていれば、a tree decomposition は次を再帰的に行うことで構成できる。 13 | 14 | 1. 次数 $2$ 以下の頂点 $v$ を好きに選ぶ。 15 | 1. 頂点 $v$ および頂点 $v$ に接続する辺をすべて取り除き (もしあれば) $v$ に隣接していた頂点間に辺を付け加えてできるグラフ $G'$ を考える。 16 | 1. $G'$ に対する a tree decomposition $T$ を求める。 17 | 1. (2.) で取り除いた辺に含まれる頂点を重み $X_i$ とするような頂点 $i$ を $T$ に追加し、$v$ に隣接していた頂点すべてを重みとして含むような頂点の子とする。 18 | 19 | 頂点に集合重みの付いた根付き木 $T = (I, F; i, X)$ が nice であるとは、おおまかには次のようにして帰納的に定められる。 20 | 21 | 1. (leaf): 頂点数 $1$ でその唯一の頂点 $i$ の重みの要素数 $\unicode{35} X_i$ が $1$ な根付き木は nice である 22 | 1. (introduce): nice な根付き木の根 $i$ の上に $X _ {i'} = X_i \cup \lbrace y \rbrace$ な新しい根を付け加えてできる根付き木は nice である 23 | 1. (forget): nice な根付き木の根 $i$ の上に $X _ {i'} = X_i \setminus \lbrace y \rbrace$ な新しい根を付け加えてできる根付き木は nice である 24 | 1. (join): nice なふたつの根付き木であって根 $i_1, i_2$ の重みが等しいものの上に $X _ i = X _ {i_1} = X _ {i_2}$ な新しい根を付け加えてできる根付き木は nice である 25 | 26 | a tree decomposition であってそれを根付き木として見たとき nice であるものを a nice tree decomposition という。 27 | a nice tree decomposition があるとその構成に沿って動的計画法ができ、その計算量は幅 $t$ に対し $O(2^t V)$ や $O(2^t t^2 V)$ などになる。 28 | -------------------------------------------------------------------------------- /graph/yen_algorithm.yukicoder-1069.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1069" 2 | #define ERROR 1e-4 3 | #include 4 | #include "../utils/macros.hpp" 5 | #include "../graph/yen_algorithm.hpp" 6 | using namespace std; 7 | 8 | int main() { 9 | // input 10 | int n, m, k; scanf("%d%d%d", &n, &m, &k); 11 | int start, goal; scanf("%d%d", &start, &goal); 12 | -- start; 13 | -- goal; 14 | vector x(n), y(n); 15 | REP (i, n) { 16 | scanf("%lld%lld", &x[i], &y[i]); 17 | } 18 | vector > > g(n); 19 | REP (i, m) { 20 | int p, q; cin >> p >> q; 21 | -- p; 22 | -- q; 23 | double cost = sqrt(pow(x[p] - x[q], 2) + pow(y[p] - y[q], 2)); 24 | g[p].emplace_back(q, cost); 25 | g[q].emplace_back(p, cost); 26 | } 27 | 28 | // solve 29 | auto path = yen_algorithm_with_dijkstra(g, start, goal, k); 30 | vector cost(k, -1); 31 | map, double> lookup; 32 | REP (i, n) { 33 | for (auto [j, cost] : g[i]) { 34 | lookup[make_pair(i, j)] = cost; 35 | } 36 | } 37 | REP (i, path.size()) { 38 | cost[i] = 0; 39 | REP (j, (int)path[i].size() - 1) { 40 | cost[i] += lookup[make_pair(path[i][j], path[i][j + 1])]; 41 | } 42 | } 43 | 44 | // output 45 | REP (i, k) { 46 | printf("%.12lf\n", cost[i]); 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /hack/fastio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | template , int> = 0> 8 | inline Char in() { return getchar_unlocked(); } 9 | template , int> = 0> 10 | inline std::string in() { 11 | char c; do { c = getchar_unlocked(); } while (isspace(c)); 12 | std::string s; 13 | do { s.push_back(c); } while (not isspace(c = getchar_unlocked())); 14 | return s; 15 | } 16 | template and not std::is_same_v, int> = 0> 17 | inline Integer in() { 18 | char c; do { c = getchar_unlocked(); } while (isspace(c)); 19 | if (std::is_signed::value and c == '-') return -in(); 20 | Integer n = 0; 21 | do { n = n * 10 + c - '0'; } while (not isspace(c = getchar_unlocked())); 22 | return n; 23 | } 24 | 25 | template , int> = 0> 26 | inline void out(char c) { putchar_unlocked(c); } 27 | template , int> = 0> 28 | inline void out(const std::string & s) { for (char c : s) putchar_unlocked(c); } 29 | template , int> = 0> 30 | inline void out(Integer n) { 31 | char s[20]; 32 | int i = 0; 33 | if (std::is_signed::value and n < 0) { putchar_unlocked('-'); n *= -1; } 34 | do { s[i ++] = n % 10; n /= 10; } while (n); 35 | while (i) putchar_unlocked(s[-- i] + '0'); 36 | } 37 | -------------------------------------------------------------------------------- /hack/fastio.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/many_aplusb" 2 | #include "../hack/fastio.hpp" 3 | 4 | int main() { 5 | int t = in(); 6 | while (t --) { 7 | uint64_t a = in(); 8 | uint64_t b = in(); 9 | out(a + b); 10 | out('\n'); 11 | } 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /hack/fastio_printer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class printer { 10 | static constexpr int N = 131072; 11 | static constexpr int K = 64; 12 | char buf[N]; 13 | int i = 0; 14 | inline void flush() { 15 | write(STDOUT_FILENO, buf, i); 16 | i = 0; 17 | } 18 | public: 19 | printer() = default; 20 | printer(const printer &) = delete; 21 | printer & operator = (const printer &) = delete; 22 | ~printer() { 23 | flush(); 24 | } 25 | template ::value, int> = 0> 26 | inline void put(char c) { 27 | if (i == N) flush(); 28 | buf[i ++] = c; 29 | } 30 | template ::value, int> = 0> 31 | void put(const std::string & s) { 32 | for (int l = 0; l < (int)s.length(); ) { 33 | if (i == N) flush(); 34 | int r = std::min(s.length(), l + (N - i)); 35 | memcpy(buf + i, s.data() + l, r - l); 36 | i += r - l; 37 | l = r; 38 | } 39 | } 40 | template ::value, int> = 0> 41 | void put(Integer x) { 42 | if (N - i < K) flush(); 43 | if (std::is_signed::value and x < 0) { 44 | x *= -1; 45 | buf[i ++] = '-'; 46 | } 47 | if (x == 0) { 48 | buf[i ++] = '0'; 49 | return; 50 | } 51 | char s[K]; 52 | int j = 0; 53 | while (x) { 54 | s[j ++] = x % 10 + '0'; 55 | x /= 10; 56 | } 57 | while (j) { 58 | buf[i ++] = s[-- j]; 59 | } 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /hack/fastio_scanner_and_printer.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/many_aplusb" 2 | #include "../hack/fastio_scanner.hpp" 3 | #include "../hack/fastio_printer.hpp" 4 | 5 | scanner sc; 6 | printer pr; 7 | 8 | int main() { 9 | int t = sc.get(); 10 | while (t --) { 11 | uint64_t a = sc.get(); 12 | uint64_t b = sc.get(); 13 | pr.put(a + b); 14 | pr.put('\n'); 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /hack/stack_pivot.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * @note This is a workaround for WSL. We cannot use ulimit -s unlimited on the environment. 6 | * @note To use such techniques, you should take care of the alignment of rsp. If not, you'll get SIGSEGV around XMM registers. 7 | */ 8 | 9 | #define BEGIN_STACK_PIVOT(STACK_SIZE) \ 10 | static volatile char *old_stack; \ 11 | asm volatile("mov %%rsp, %0" : "=r" (old_stack) ); \ 12 | char *new_stack = ((char *)malloc(STACK_SIZE) + (STACK_SIZE) - 0x10); \ 13 | asm volatile("mov %0, %%rsp" : : "r" (new_stack) ); 14 | 15 | #define END_STACK_PIVOT() \ 16 | asm volatile("mov %0, %%rsp" : : "r" (old_stack) ); 17 | 18 | #define STACK_PIVOT_MAIN(moin) \ 19 | int main() { \ 20 | BEGIN_STACK_PIVOT(1 << 28) \ 21 | static int returncode = moin(); \ 22 | END_STACK_PIVOT() \ 23 | return returncode; \ 24 | } 25 | -------------------------------------------------------------------------------- /library.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmyk/competitive-programming-library/77efa23a69f06202bb43f4dc6b0550e4cdb48e0b/library.pdf -------------------------------------------------------------------------------- /modulus/bell_number.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../modulus/mint.hpp" 3 | #include "../modulus/choose.hpp" 4 | #include "../modulus/stirling_number_of_the_second_kind_table.hpp" 5 | 6 | /** 7 | * @brief the Bell number (前処理 $O(NK)$ + $O(1)$) 8 | * @description the number of ways a set of n elements can be partitioned into nonempty subsets 9 | * @see http://mathworld.wolfram.com/BellNumber.html 10 | * @see https://oeis.org/A110 11 | * @see https://ja.wikipedia.org/wiki/%E3%83%99%E3%83%AB%E6%95%B0 12 | */ 13 | template 14 | mint bell_number(int n, int k) { 15 | static std::vector > > memo; 16 | if (memo.size() <= n) { 17 | memo.resize(n + 1); 18 | } 19 | if (memo[n].empty()) { 20 | memo[n].push_back(0); 21 | } 22 | while (memo[n].size() <= k) { 23 | int i = memo[n].size(); 24 | memo[n].push_back(memo[n].back() + stirling_number_of_the_second_kind_table(n, i)); 25 | } 26 | return memo[n][k]; 27 | } 28 | 29 | template 30 | mint unary_bell_number(int n) { 31 | return bell_number(n, n); 32 | } 33 | -------------------------------------------------------------------------------- /modulus/choose.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../modulus/mint.hpp" 4 | #include "../modulus/factorial.hpp" 5 | 6 | /** 7 | * @brief combination / 組合せ ${} _ n C _ r$ (前処理 $O(n)$ + $O(1)$) 8 | */ 9 | template 10 | mint choose(int n, int r) { 11 | assert (0 <= r and r <= n); 12 | return fact(n) * inv_fact(n - r) * inv_fact(r); 13 | } 14 | -------------------------------------------------------------------------------- /modulus/choose.yukicoder-1035.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1035" 2 | #include 3 | #include "../utils/macros.hpp" 4 | #include "../modulus/mint.hpp" 5 | #include "../modulus/choose.hpp" 6 | using namespace std; 7 | 8 | constexpr int64_t MOD = 1000000007; 9 | mint solve(int n, int m) { 10 | mint ans = 0; 11 | REP (i, m + 1) { 12 | int sign = (i % 2 == 0 ? 1 : -1); 13 | ans += sign * choose(m, m - i) * mint(m - i).pow(n); 14 | } 15 | return ans; 16 | } 17 | 18 | int main() { 19 | int N, M; cin >> N >> M; 20 | cout << solve(N, M) << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /modulus/choose_simple.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../modulus/mint.hpp" 4 | #include "../utils/macros.hpp" 5 | 6 | /** 7 | * @brief combination / 組合せ ${} _ n C _ r$ (愚直 $O(r)$) 8 | */ 9 | template 10 | mint choose_simple(int64_t n, int32_t r) { 11 | assert (0 <= r and r <= n); 12 | mint num = 1; 13 | mint den = 1; 14 | REP (i, r) { 15 | num *= n - i; 16 | den *= i + 1; 17 | } 18 | return num / den; 19 | } 20 | -------------------------------------------------------------------------------- /modulus/factorial.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../modulus/mint.hpp" 4 | 5 | template 6 | mint fact(int n) { 7 | static std::vector > memo(1, 1); 8 | while (n >= memo.size()) { 9 | memo.push_back(memo.back() * mint(memo.size())); 10 | } 11 | return memo[n]; 12 | } 13 | template 14 | mint inv_fact(int n) { 15 | static std::vector > memo; 16 | if (memo.size() <= n) { 17 | int l = memo.size(); 18 | int r = n * 1.3 + 100; 19 | memo.resize(r); 20 | memo[r - 1] = fact(r - 1).inv(); 21 | for (int i = r - 2; i >= l; -- i) { 22 | memo[i] = memo[i + 1] * (i + 1); 23 | } 24 | } 25 | return memo[n]; 26 | } 27 | -------------------------------------------------------------------------------- /modulus/formal_power_series.exp.test.cpp: -------------------------------------------------------------------------------- 1 | #include "../modulus/formal_power_series.hpp" 2 | #define PROBLEM "https://judge.yosupo.jp/problem/exp_of_formal_power_series" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | using namespace std; 8 | 9 | constexpr int MOD = 998244353; 10 | int main() { 11 | // input 12 | int n; scanf("%d", &n); 13 | vector > a(n); 14 | REP (i, n) { 15 | scanf("%d", &a[i].value); 16 | } 17 | 18 | // solve 19 | vector > b = formal_power_series >(a).exp(n).data(); 20 | b.resize(n); 21 | 22 | // output 23 | REP (i, n) { 24 | printf("%d ", b[i].value); 25 | } 26 | printf("\n"); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /modulus/formal_power_series.inv.test.cpp: -------------------------------------------------------------------------------- 1 | #include "../modulus/formal_power_series.hpp" 2 | #define PROBLEM "https://judge.yosupo.jp/problem/inv_of_formal_power_series" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | using namespace std; 8 | 9 | constexpr int MOD = 998244353; 10 | int main() { 11 | // input 12 | int n; scanf("%d", &n); 13 | vector > a(n); 14 | REP (i, n) { 15 | scanf("%d", &a[i].value); 16 | } 17 | 18 | // solve 19 | vector > b = formal_power_series >(a).inv(n).data(); 20 | b.resize(n); 21 | 22 | // output 23 | REP (i, n) { 24 | printf("%d ", b[i].value); 25 | } 26 | printf("\n"); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /modulus/formal_power_series.log.test.cpp: -------------------------------------------------------------------------------- 1 | #include "../modulus/formal_power_series.hpp" 2 | #define PROBLEM "https://judge.yosupo.jp/problem/log_of_formal_power_series" 3 | 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | using namespace std; 8 | 9 | constexpr int MOD = 998244353; 10 | int main() { 11 | // input 12 | int n; scanf("%d", &n); 13 | vector > a(n); 14 | REP (i, n) { 15 | scanf("%d", &a[i].value); 16 | } 17 | 18 | // solve 19 | vector > b = formal_power_series >(a).log(n).data(); 20 | b.resize(n); 21 | 22 | // output 23 | REP (i, n) { 24 | printf("%d ", b[i].value); 25 | } 26 | printf("\n"); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /modulus/formal_power_series.yukicoder-1145.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1145" 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | #include "../modulus/mint.hpp" 6 | #include "../modulus/formal_power_series.hpp" 7 | using namespace std; 8 | 9 | constexpr int MOD = 998244353; 10 | vector > solve(int n, int m, const vector > & a) { 11 | auto go = [&](auto && go, int l, int r) { 12 | if (r - l == 0) return formal_power_series >{ 1 }; 13 | if (r - l == 1) return formal_power_series >{ 1, - a[l] }; 14 | int m_ = (l + r) / 2; 15 | return (go(go, l, m_) * go(go, m_, r)).modulo_x_to(m + 2); 16 | }; 17 | vector > ans = (- go(go, 0, n).log(m + 2)).data(); 18 | ans.resize(m + 1); 19 | REP3 (k, 1, m + 1) { 20 | ans[k] *= k; 21 | } 22 | return ans; 23 | } 24 | 25 | int main() { 26 | int n, m; scanf("%d%d", &n, &m); 27 | vector > a(n); 28 | REP (i, n) { 29 | scanf("%d", &a[i].value); 30 | } 31 | auto ans = solve(n, m, a); 32 | assert (ans[0] == 0); 33 | REP (i, m) { 34 | printf("%d%c", ans[i + 1].value, i + 1 < m ? ' ' : '\n'); 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /modulus/garner.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../modulus/mint.hpp" 8 | #include "../utils/macros.hpp" 9 | 10 | /** 11 | * @brief Garner's algorithm 12 | * @arg eqns is equations like x = a_i (mod m_i) 13 | * @return the minimal solution of given equations 14 | */ 15 | int32_t garner_algorithm(std::vector > eqns, int32_t MOD) { 16 | eqns.emplace_back(0, MOD); 17 | std::vector k(eqns.size(), 1); 18 | std::vector c(eqns.size(), 0); 19 | REP (i, eqns.size() - 1) { 20 | int32_t a_i, m_i; std::tie(a_i, m_i) = eqns[i]; 21 | 22 | int32_t x = (a_i - c[i]) * modinv(k[i], m_i) % m_i; 23 | if (x < 0) x += m_i; 24 | assert (a_i == (k[i] * x + c[i]) % m_i); 25 | 26 | REP3 (j, i + 1, eqns.size()) { 27 | int32_t a_j, m_j; std::tie(a_j, m_j) = eqns[j]; 28 | (c[j] += k[j] * x) %= m_j; 29 | (k[j] *= m_i) %= m_j; 30 | } 31 | } 32 | return c.back(); 33 | } 34 | -------------------------------------------------------------------------------- /modulus/mint_with_zero.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://atcoder.jp/contests/arc117/tasks/arc117_c" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | #include "../modulus/mint.hpp" 8 | #include "../modulus/mint_with_zero.hpp" 9 | using namespace std; 10 | 11 | int solve(int n, const std::vector& a) { 12 | std::vector > fact(n + 1); 13 | fact[0] = 1; 14 | REP (i, n) { 15 | fact[i + 1] = (i + 1) * fact[i]; 16 | } 17 | auto choose = [&](int n, int r) { 18 | return (fact[n] * fact[n - r].inv() * fact[r].inv()).to_mint(); 19 | }; 20 | 21 | mint<3> b = 0; 22 | REP (i, n) { 23 | b += choose(n - 1, i) * a[i]; 24 | } 25 | if (n % 2 == 0) { 26 | b *= -1; 27 | } 28 | return b.value; 29 | } 30 | 31 | int main() { 32 | int n; std::cin >> n; 33 | std::string s; std::cin >> s; 34 | assert (s.length() == n); 35 | std::vector a(n); 36 | REP (i, n) { 37 | a[i] = (s[i] == 'W' ? 0 : s[i] == 'R' ? 1 : s[i] == 'B' ? 2 : -1); 38 | assert (a[i] != -1); 39 | } 40 | int ans = solve(n, a); 41 | assert (0 <= ans and ans < 3); 42 | std::array table = {{ 'W', 'R', 'B' }}; 43 | std::cout << table[ans] << std::endl; 44 | return 0; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /modulus/modinv.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | inline int32_t modinv_nocheck(int32_t value, int32_t MOD) { 7 | assert (0 <= value and value < MOD); 8 | if (value == 0) return -1; 9 | int64_t a = value, b = MOD; 10 | int64_t x = 0, y = 1; 11 | for (int64_t u = 1, v = 0; a; ) { 12 | int64_t q = b / a; 13 | x -= q * u; std::swap(x, u); 14 | y -= q * v; std::swap(y, v); 15 | b -= q * a; std::swap(b, a); 16 | } 17 | if (not (value * x + MOD * y == b and b == 1)) return -1; 18 | if (x < 0) x += MOD; 19 | assert (0 <= x and x < MOD); 20 | return x; 21 | } 22 | 23 | inline int32_t modinv(int32_t x, int32_t MOD) { 24 | int32_t y = modinv_nocheck(x, MOD); 25 | assert (y != -1); 26 | return y; 27 | } 28 | -------------------------------------------------------------------------------- /modulus/modlog.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../modulus/modinv.hpp" 8 | #include "../modulus/modpow.hpp" 9 | #include "../utils/macros.hpp" 10 | #include 11 | 12 | /** 13 | * @brief discrete log / 離散対数 (the baby-step giant-step, $O(\sqrt{m})$) 14 | * @description find the smallest $x \ge 0$ s.t. $g^x \equiv y \pmod{m}$ 15 | * @param m is a positive integer 16 | * @note -1 if not found 17 | */ 18 | inline int modlog(int g, int y, int m) { 19 | assert (0 <= g and g < m); 20 | assert (0 <= y and y < m); 21 | if (m == 1) return 0; 22 | if (y == 1) return 0; 23 | if (g == 0 and y == 0) return 1; 24 | 25 | // meet-in-the-middle; let x = a \sqrt{m} + b 26 | int sqrt_m = sqrt(m) + 100; // + 100 is required to bruteforce g^b for b < 100; this avoids problems with g != 0 and y = 0 27 | assert (sqrt_m >= 0); 28 | 29 | // baby-step: list (y, gy, g^2 y, ...) = (g^x, g^{x + 1}, g^{x + 2}, ...) 30 | std::unordered_map table; 31 | int baby = 1; 32 | REP (b, sqrt_m) { 33 | if (baby == y) return b; 34 | table[(int64_t)baby * y % m] = b; 35 | baby = (int64_t)baby * g % m; 36 | } 37 | 38 | // giant-step: list (g^{sqrt(m)}, g^{2 sqrt(m)}, g^{3 sqrt(m)}, ...) 39 | int giant = 1; 40 | REP3 (a, 1, sqrt_m + 3) { 41 | giant = (int64_t)giant * baby % m; 42 | auto it = table.find(giant); 43 | if (it != table.end()) { 44 | int b = it->second; 45 | int x = (int64_t)a * sqrt_m - b; 46 | assert (x >= 0); 47 | return (modpow(g, x, m) == y ? x : -1); 48 | } 49 | } 50 | return -1; 51 | } 52 | -------------------------------------------------------------------------------- /modulus/modlog.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/discrete_logarithm_mod" 2 | #include "../modulus/modlog.hpp" 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | int t; scanf("%d", &t); 10 | while (t --) { 11 | int x, y, m; scanf("%d%d%d", &x, &y, &m); 12 | int k = modlog(x, y, m); 13 | printf("%d\n", k); 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /modulus/modlog.yuki1255.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1255" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../utils/macros.hpp" 8 | #include "../modulus/modinv.hpp" 9 | #include "../modulus/modlog.hpp" 10 | using namespace std; 11 | 12 | int64_t solve(int64_t n) { 13 | if (n == 1) return 1; 14 | if (n == 2) return 2; 15 | assert (n >= 3); 16 | 17 | int64_t m = 2 * n - 1; 18 | auto f = [&](int64_t aq, int64_t ar, int64_t bq, int64_t br) { 19 | int64_t cq = aq + bq; 20 | int64_t cr = ar + br; 21 | if (cr >= m) { 22 | cr -= m; 23 | cq += 1; 24 | } 25 | return make_pair(cq, cr); 26 | }; 27 | 28 | int64_t k = modlog(2, modinv(2, m), m) + 1; 29 | int64_t q0 = 0; 30 | int64_t r0 = 0; 31 | int64_t q1 = 0; 32 | int64_t r1 = 1; 33 | REP (i, 60) { 34 | if (k & (1ll << i)) { 35 | tie(q0, r0) = f(q0, r0, q1, r1); 36 | } 37 | tie(q1, r1) = f(q1, r1, q1, r1); 38 | } 39 | return k + q0; 40 | } 41 | 42 | int main() { 43 | int t; cin >> t; 44 | while (t --) { 45 | int64_t n; cin >> n; 46 | cout << solve(n) << endl; 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /modulus/modpow.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | inline int32_t modpow(uint_fast64_t x, uint64_t k, int32_t MOD) { 6 | assert (/* 0 <= x and */ x < (uint_fast64_t)MOD); 7 | uint_fast64_t y = 1; 8 | for (; k; k >>= 1) { 9 | if (k & 1) (y *= x) %= MOD; 10 | (x *= x) %= MOD; 11 | } 12 | assert (/* 0 <= y and */ y < (uint_fast64_t)MOD); 13 | return y; 14 | } 15 | -------------------------------------------------------------------------------- /modulus/modsqrt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../modulus/modpow.hpp" 5 | 6 | /** 7 | * @brief find the sqrt $b$ of $a$ modulo $p$ 8 | * @param p must be a prime 9 | * @note i.e. $b^2 \equiv a \pmod{p}$ 10 | * @note -1 if not found 11 | */ 12 | int modsqrt(int a, int p) { 13 | auto legendre_symbol = [&](int a) { 14 | return modpow(a, (p - 1) / 2, p); // Euler's criterion 15 | }; 16 | a %= p; 17 | if (a == 0) return 0; 18 | if (p == 2) return a; 19 | assert (p >= 3); 20 | if (legendre_symbol(a) != +1) return -1; 21 | int b = 1; 22 | while (legendre_symbol(b) == 1) { 23 | b += 1; 24 | } 25 | int e = 0; 26 | int m = p - 1; 27 | while (m % 2 == 0) { 28 | m /= 2; 29 | e += 1; 30 | } 31 | int64_t x = modpow(a, (m - 1) / 2, p); 32 | int64_t y = a * x % p * x % p; 33 | x = x * a % p; 34 | int64_t z = modpow(b, m, p); 35 | while (y != 1) { 36 | int j = 0; 37 | for (int64_t t = y; t != 1; t = t * t % p) ++ j; 38 | if (e <= j) return -1; 39 | z = modpow(z, 1ll << (e - j - 1), p); 40 | x = x * z % p; 41 | z = z * z % p; 42 | y = y * z % p; 43 | e = j; 44 | } 45 | assert (x * x % p == a); 46 | return x; 47 | } 48 | -------------------------------------------------------------------------------- /modulus/modsqrt.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/sqrt_mod" 2 | #include "../modulus/modsqrt.hpp" 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | int t; scanf("%d", &t); 10 | while (t --) { 11 | int y, p; scanf("%d%d", &y, &p); 12 | int x = modsqrt(y, p); 13 | printf("%d\n", x); 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /modulus/multichoose.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../modulus/mint.hpp" 4 | #include "../modulus/choose.hpp" 5 | 6 | /** 7 | * @brief 重複組合せ ${} _ n H _ r = {} _ {n + r - 1} C _ r$ (前処理 $O(n)$ + $O(1)$) 8 | */ 9 | template 10 | mint multichoose(int n, int r) { 11 | assert (0 <= n and 0 <= r); 12 | if (n == 0 and r == 0) return 1; 13 | return choose(n + r - 1, r); 14 | } 15 | -------------------------------------------------------------------------------- /modulus/multichoose_simple.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../modulus/mint.hpp" 4 | #include "../modulus/choose_simple.hpp" 5 | 6 | /** 7 | * @brief 重複組合せ ${} _ n H _ r = {} _ {n + r - 1} C _ r$ (愚直 $O(r)$) 8 | */ 9 | template 10 | mint multichoose_simple(int64_t n, int32_t r) { 11 | assert (0 <= n and 0 <= r); 12 | if (n == 0 and r == 0) return 1; 13 | return choose_simple(n + r - 1, r); 14 | } 15 | -------------------------------------------------------------------------------- /modulus/number_theoretic_transformation.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #include "../modulus/number_theoretic_transformation.hpp" 2 | #define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod" 3 | 4 | #include 5 | #include "../utils/macros.hpp" 6 | #include "../hack/fastio.hpp" 7 | 8 | constexpr int MOD = 998244353; 9 | int main() { 10 | // input 11 | int n = in(); 12 | int m = in(); 13 | std::vector > a(n); 14 | REP (i, n) { 15 | a[i].value = in(); 16 | } 17 | std::vector > b(m); 18 | REP (j, m) { 19 | b[j].value = in(); 20 | } 21 | 22 | // solve 23 | std::vector > c = ntt_convolution(a, b); 24 | 25 | // output 26 | REP (i, n + m - 1) { 27 | out(c[i].value); 28 | out(' '); 29 | } 30 | out('\n'); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /modulus/number_theoretic_transformation_with_garner.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #include "../modulus/number_theoretic_transformation_with_garner.hpp" 2 | #define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod_1000000007" 3 | 4 | #include 5 | #include "../utils/macros.hpp" 6 | #include "../hack/fastio.hpp" 7 | 8 | constexpr int MOD = 1000000007; 9 | int main() { 10 | // input 11 | int n = in(); 12 | int m = in(); 13 | std::vector > a(n); 14 | REP (i, n) { 15 | a[i].value = in(); 16 | } 17 | std::vector > b(m); 18 | REP (j, m) { 19 | b[j].value = in(); 20 | } 21 | 22 | // solve 23 | std::vector > c = ntt_convolution(a, b); 24 | 25 | // output 26 | REP (i, n + m - 1) { 27 | out(c[i].value); 28 | out(' '); 29 | } 30 | out('\n'); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /modulus/partition_number.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../modulus/mint.hpp" 3 | #include "../modulus/choose.hpp" 4 | #include "../modulus/stirling_number_of_the_second_kind_table.hpp" 5 | 6 | /** 7 | * @brief the partition number (前処理 $O(NK)$ + $O(1)$) 8 | * @description the number of non-decreasing sequences with the length k which the sum is n 9 | */ 10 | template 11 | mint partition_number(int n, int k) { 12 | static std::vector > > memo; 13 | if (memo.size() <= n) { 14 | memo.resize(n + 1); 15 | } 16 | while (memo[n].size() <= k) { 17 | if (n == 0) { 18 | memo[0].resize(k + 1, 1); 19 | } else if (memo[n].empty()) { 20 | memo[n].push_back(0); 21 | } else { 22 | int j = memo[n].size(); 23 | auto a = (n - j >= 0 ? partition_number(n - j, j) : 0); 24 | auto b = (j - 1 >= 0 ? partition_number(n, j - 1) : 0); 25 | memo[n].push_back(a + b); 26 | } 27 | } 28 | return memo[n][k]; 29 | } 30 | 31 | template 32 | mint unary_partition_number(int n) { 33 | return partition_number(n, n); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /modulus/permute.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../modulus/mint.hpp" 4 | #include "../modulus/factorial.hpp" 5 | 6 | /** 7 | * @brief permutation / 順列 ${} _ n P _ r$ (前処理 $O(n)$ + $O(1)$) 8 | */ 9 | template 10 | mint permute(int n, int r) { 11 | assert (0 <= r and r <= n); 12 | return fact(n) * inv_fact(n - r); 13 | } 14 | -------------------------------------------------------------------------------- /modulus/stirling_number_of_the_second_kind_convolution.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../modulus/mint.hpp" 5 | #include "../modulus/factorial.hpp" 6 | #include "../modulus/number_theoretic_transformation_with_garner.hpp" 7 | 8 | /** 9 | * @brief the Stirling number of the second kind (for given $N$, compute $S(N, \ast)$ in $O(N \log N)$) 10 | * @see https://min-25.hatenablog.com/entry/2015/04/07/160154 11 | */ 12 | template 13 | std::vector > stirling_number_of_the_second_kind_convolution(int n) { 14 | assert (0 <= n); 15 | std::vector > a(n + 1); 16 | std::vector > b(n + 1); 17 | REP (i, n + 1) { 18 | a[i] = mint(i).pow(n) * inv_fact(i); 19 | b[i] = (i % 2 == 0 ? 1 : -1) * inv_fact(i); 20 | } 21 | auto c = ntt_convolution(a, b); 22 | c.resize(n + 1); 23 | return c; 24 | } 25 | -------------------------------------------------------------------------------- /modulus/stirling_number_of_the_second_kind_convolution.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/stirling_number_of_the_second_kind" 2 | #include "../modulus/stirling_number_of_the_second_kind_convolution.hpp" 3 | #include "../hack/fastio.hpp" 4 | #include "../utils/macros.hpp" 5 | 6 | constexpr int MOD = 998244353; 7 | int main() { 8 | int n = in(); 9 | auto f = stirling_number_of_the_second_kind_convolution(n); 10 | REP (k, n + 1) { 11 | out(f[k].value); 12 | out(k < n ? ' ' : '\n'); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /modulus/stirling_number_of_the_second_kind_direct.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../utils/macros.hpp" 6 | #include "../modulus/mint.hpp" 7 | #include "../modulus/factorial.hpp" 8 | #include "../modulus/choose.hpp" 9 | 10 | /** 11 | * @brief the Stirling number of the second kind ($O(K \log N)$) 12 | */ 13 | template 14 | mint stirling_number_of_the_second_kind_direct(int n, int k) { 15 | assert (0 <= n and 0 <= k); 16 | mint acc = 0; 17 | REP (i, k + 1) { 18 | int parity = ((k - i) % 2 == 0 ? +1 : -1); 19 | acc += choose(k, i) * mint(i).pow(n) * parity; 20 | } 21 | return acc * inv_fact(k); 22 | } 23 | -------------------------------------------------------------------------------- /modulus/stirling_number_of_the_second_kind_table.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | #include "../modulus/mint.hpp" 6 | 7 | /** 8 | * @brief the Stirling number of the second kind (前処理 $O(NK)$ + $O(1)$) 9 | * @description the number of ways of partitioning a set of n elements into k nonempty sets 10 | * @see http://mathworld.wolfram.com/StirlingNumberoftheSecondKind.html 11 | * @see http://oeis.org/A008277 12 | * @see https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E6%95%B0#.E7.AC.AC2.E7.A8.AE.E3.82.B9.E3.82.BF.E3.83.BC.E3.83.AA.E3.83.B3.E3.82.B0.E6.95.B0 13 | */ 14 | template 15 | mint stirling_number_of_the_second_kind_table(int n, int k) { 16 | assert (0 <= n and 0 <= k); 17 | if (n < k) return 0; 18 | if (n == k) return 1; 19 | if (k == 0) return 0; 20 | static std::vector > > memo; 21 | if (memo.size() <= n) { 22 | int l = memo.size(); 23 | memo.resize(n + 1); 24 | REP3 (i, l, n + 1) { 25 | memo[i].resize(i); 26 | } 27 | } 28 | if (memo[n][k]) return memo[n][k]; 29 | return memo[n][k] = 30 | stirling_number_of_the_second_kind_table(n - 1, k - 1) + 31 | stirling_number_of_the_second_kind_table(n - 1, k) * k; 32 | } 33 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_1.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_A" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_lla(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_10.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_J" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_uua(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_11.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_K" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_uui(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_B" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_lli(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_3.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_C" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_lls(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_4.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_D" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_ula(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_5.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_E" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_uli(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_6.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_F" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_uls(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_7.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_G" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_lua(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_8.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_H" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_lui(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /modulus/twelvefold_way.balls_and_boxes_9.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_I" 2 | #include 3 | #include "../modulus/twelvefold_way.hpp" 4 | using namespace std; 5 | 6 | constexpr int MOD = 1e9 + 7; 7 | int main() { 8 | int n, k; cin >> n >> k; 9 | cout << twelvefold_lus(n, k) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /monoids/chmin_chmax_add.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * @note represents the monoid $M = (\lbrace \lambda x. \min(a, \max(b, c + x)) \mid a, b, c \rbrace, \circ, \mathrm{id})$ 8 | */ 9 | template 10 | struct chmin_chmax_add_monoid { 11 | static constexpr MAX = std::numeric_limits::max(); 12 | static constexpr MIN = std::numeric_limits::lowest(); 13 | struct value_type { 14 | long long chmin; 15 | long long chmax; 16 | long long add; 17 | }; 18 | value_type unit() const { 19 | return (value_type) { MAX, MIN, 0 }; 20 | } 21 | value_type mult(value_type a, value_type b) const { 22 | value_type c = b; 23 | // add 24 | if (c.chmin != MAX) { 25 | c.chmin += a.add; 26 | } 27 | if (c.chmax != MIN) { 28 | c.chmax += a.add; 29 | } 30 | c.add += a.add; 31 | // chmax 32 | c.chmin = std::max(a.chmax, c.chmin); 33 | c.chmax = std::max(a.chmax, c.chmax); 34 | // chmin 35 | c.chmin = std::min(a.chmin, c.chmin); 36 | return c; 37 | } 38 | static value_type chmin(T value) { 39 | return (value_type) { value, MIN, 0 }; 40 | } 41 | static value_type chmin(T value) { 42 | return (value_type) { MAX, value, 0 }; 43 | } 44 | static value_type chmin(T value) { 45 | return (value_type) { MAX, MIN, value }; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /monoids/chmin_chmax_add_min_max_action.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../monoids/chmin_chmax_add.hpp" 7 | #include "../monoids/min_max.hpp" 8 | 9 | template 10 | struct chmin_chmax_add_min_max_action { 11 | typedef typename chmin_chmax_add_monoid::value_type F; 12 | typedef typename min_max_monoid::value_type X; 13 | X operator () (F f, X x) const { 14 | if (x.first == std::numeric_limits::max()) { 15 | assert (x.second == std::numeric_limits::lowest()); 16 | return x; 17 | } 18 | T a = std::min(f.chmin, std::max(f.chmax, f.add + x.first)); 19 | T b = std::min(f.chmin, std::max(f.chmax, f.add + x.second)); 20 | return std::make_pair(a, b); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /monoids/dual.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * @see http://hackage.haskell.org/package/base/docs/Data-Monoid.html#t:Dual 5 | */ 6 | template 7 | struct dual_monoid { 8 | typedef typename Monoid::value_type value_type; 9 | Monoid base; 10 | value_type unit() const { return base.unit(); } 11 | value_type mult(const value_type & a, const value_type & b) const { return base.mult(b, a); } 12 | }; 13 | -------------------------------------------------------------------------------- /monoids/gcd.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../number/gcd.hpp" 3 | 4 | /** 5 | * @note a semilattice 6 | */ 7 | template 8 | struct gcd_monoid { 9 | typedef Integer value_type; 10 | Integer unit() const { return 0; } 11 | Integer mult(Integer a, Integer b) const { return gcd(a, b); } 12 | }; 13 | -------------------------------------------------------------------------------- /monoids/left.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | struct left_monoid { 6 | // typedef std::optional value_type; 7 | typedef std::pair value_type; 8 | value_type unit() const { return std::make_pair(false, T()); } 9 | value_type mult(value_type a, value_type b) const { return a.first ? a : b; } 10 | }; 11 | -------------------------------------------------------------------------------- /monoids/left_action.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../monoids/left.hpp" 4 | 5 | /** 6 | * @note lazy_propagation_segment_tree, Monoid, left_action > is the same to dual_segment_tree 7 | */ 8 | template 9 | struct left_action { 10 | typename left_monoid::value_type operator () (typename Monoid::value_type f, typename left_monoid::value_type x) const { 11 | return x.first ? std::make_pair(true, Monoid().mult(f, x.second)) : x; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /monoids/linear_function.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | struct linear_function_monoid { 6 | typedef std::pair value_type; 7 | linear_function_monoid() = default; 8 | value_type unit() const { 9 | return std::make_pair(1, 0); 10 | } 11 | value_type mult(value_type g, value_type f) const { 12 | CommutativeRing fst = g.first * f.first; 13 | CommutativeRing snd = g.second + g.first * f.second; 14 | return std::make_pair(fst, snd); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /monoids/linear_function_plus_count_action.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../monoids/linear_function.hpp" 4 | 5 | /** 6 | * @note lazy_propagation_segment_tree, linear_function_monoid, linear_function_plus_count_action > 7 | */ 8 | template 9 | struct linear_function_plus_count_action { 10 | typename plus_count_monoid::value_type operator () (typename linear_function_monoid::value_type f, typename plus_count_monoid::value_type x) const { 11 | return std::make_pair(f.first * x.first + f.second * x.second, x.second); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /monoids/matrix_template.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../number/matrix_template.hpp" 3 | 4 | template 5 | struct matrix_monoid { 6 | typedef matrix value_type; 7 | value_type f; 8 | value_type unit() const { 9 | return unit_matrix(); 10 | } 11 | value_type mult(const value_type & f, const value_type & g) const { 12 | return f * g; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /monoids/max.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | template 6 | struct max_monoid { 7 | typedef T value_type; 8 | value_type unit() const { return std::numeric_limits::lowest(); } 9 | value_type mult(value_type a, value_type b) const { return std::max(a, b); } 10 | }; 11 | -------------------------------------------------------------------------------- /monoids/max_index.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * @note a semilattice 9 | */ 10 | template 11 | struct max_index_monoid { 12 | typedef std::pair value_type; 13 | value_type unit() const { return std::make_pair(std::numeric_limits::lowest(), INT_MIN); } 14 | value_type mult(value_type a, value_type b) const { return std::max(a, b); } 15 | }; 16 | -------------------------------------------------------------------------------- /monoids/min.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | template 6 | struct min_monoid { 7 | typedef T value_type; 8 | value_type unit() const { return std::numeric_limits::max(); } 9 | value_type mult(value_type a, value_type b) const { return std::min(a, b); } 10 | }; 11 | -------------------------------------------------------------------------------- /monoids/min_count.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | template 6 | struct min_count_monoid { 7 | typedef std::pair value_type; 8 | value_type unit() const { 9 | return std::make_pair(std::numeric_limits::max(), 0); 10 | } 11 | value_type mult(value_type a, value_type b) const { 12 | if (a.first < b.first) return a; 13 | if (a.first > b.first) return b; 14 | return std::make_pair(a.first, a.second + b.second); 15 | } 16 | static value_type make(T a) { 17 | return std::make_pair(a, 1); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /monoids/min_index.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * @note a semilattice 9 | */ 10 | template 11 | struct min_index_monoid { 12 | typedef std::pair value_type; 13 | value_type unit() const { return std::make_pair(std::numeric_limits::max(), INT_MAX); } 14 | value_type mult(value_type a, value_type b) const { return std::min(a, b); } 15 | }; 16 | -------------------------------------------------------------------------------- /monoids/min_max.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | struct min_max_monoid { 8 | typedef std::pair value_type; 9 | value_type unit() const { 10 | return std::make_pair(std::numeric_limits::max(), std::numeric_limits::lowest()); 11 | } 12 | value_type mult(value_type a, value_type b) const { 13 | return std::make_pair(std::min(a.min, b.min), std::max(a.max, b.max)); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /monoids/plus.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | struct plus_monoid { 5 | typedef T value_type; 6 | value_type unit() const { return value_type(); } 7 | value_type mult(value_type a, value_type b) const { return a + b; } 8 | }; 9 | -------------------------------------------------------------------------------- /monoids/plus_count.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | struct plus_count_monoid { 6 | typedef std::pair value_type; 7 | value_type unit() const { 8 | return std::make_pair(T(), 0); 9 | } 10 | value_type mult(value_type a, value_type b) const { 11 | return std::make_pair(a.first + b.first, a.second + b.second); 12 | } 13 | static value_type make(T a) { 14 | return std::make_pair(a, 1); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /monoids/plus_max_action.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../monoids/plus.hpp" 3 | #include "../monoids/max.hpp" 4 | 5 | /** 6 | * @note lazy_propagation_segment_tree, plus_monoid, plus_max_action > is a starry sky tree 7 | */ 8 | template 9 | struct plus_max_action { 10 | typename max_monoid::value_type operator () (typename plus_monoid::value_type f, typename max_monoid::value_type x) const { 11 | return (x == max_monoid().unit() ? x : f + x); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /monoids/plus_min_action.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../monoids/plus.hpp" 3 | #include "../monoids/min.hpp" 4 | 5 | template 6 | struct plus_min_action { 7 | typename min_monoid::value_type operator () (typename plus_monoid::value_type f, typename min_monoid::value_type x) const { 8 | return (x == min_monoid().unit() ? x : f + x); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /monoids/plus_min_count_action.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../monoids/plus.hpp" 4 | #include "../monoids/min_count.hpp" 5 | 6 | /** 7 | * @note lazy_propagation_segment_tree, plus_monoid, plus_min_count_action > can count a number of zeros (or, non-zero numbers) in the array 8 | */ 9 | template 10 | struct plus_min_count_action { 11 | typename min_count_monoid::value_type operator () (typename plus_monoid::value_type f, typename min_count_monoid::value_type x) const { 12 | if (x.first == min_count_monoid().unit().first) return x; 13 | return std::make_pair(f + x.first, x.second); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /monoids/product.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | struct product_monoid { 6 | typedef std::pair value_type; 7 | Monoid1 mon1; 8 | Monoid2 mon2; 9 | value_type unit() const { 10 | return std::make_pair(mon1.unit(), mon2.unit()); 11 | } 12 | value_type mult(value_type a, value_type b) const { 13 | return std::make_pair(mon1.mult(a.first, b.first), mon2.mult(a.second, b.second)); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /monoids/reversible.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | struct reversible_monoid { 6 | typedef typename Monoid::value_type base_type; 7 | typedef std::pair value_type; 8 | Monoid base; 9 | reversible_monoid() = default; 10 | reversible_monoid(const Monoid & base_) : base(base_) {} 11 | value_type unit() const { return std::make_pair(base.unit(), base.unit()); } 12 | value_type mult(const value_type & a, const value_type & b) const { return std::make_pair(base.mult(a.first, b.first), base.mult(b.second, a.second)); } 13 | static value_type make(const base_type & x) { return std::make_pair(x, x); } 14 | static value_type reverse(const value_type & a) { return std::make_pair(a.second, a.first); } 15 | static base_type get(const value_type & a) { return a.first; } 16 | }; 17 | -------------------------------------------------------------------------------- /monoids/trivial.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct trivial_monoid { 4 | typedef struct {} value_type; 5 | value_type unit() const { return (value_type) {}; } 6 | value_type mult(value_type a, value_type b) const { return (value_type) {}; } 7 | }; 8 | -------------------------------------------------------------------------------- /monoids/trivial_action.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../monoids/trivial.hpp" 3 | 4 | /** 5 | * @note lazy_propagation_segment_tree > is the same to segment_tree 6 | */ 7 | template 8 | struct trivial_action { 9 | T operator () (typename trivial_monoid::value_type f, T x) const { return x; } 10 | }; 11 | -------------------------------------------------------------------------------- /number/gcd.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * @note if arguments are negative, the result may be negative 6 | */ 7 | template 8 | T gcd(T a, T b) { 9 | while (a) { 10 | b %= a; 11 | std::swap(a, b); 12 | } 13 | return b; 14 | } 15 | 16 | template 17 | T lcm(T a, T b) { 18 | return a / gcd(a, b) * b; 19 | } 20 | -------------------------------------------------------------------------------- /number/inversion_number.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../data_structure/binary_indexed_tree.hpp" 5 | #include "../utils/macros.hpp" 6 | #include "../monoids/plus.hpp" 7 | 8 | int64_t inversion_number(const std::vector &a) { 9 | int n = a.size(); 10 | binary_indexed_tree> bit(n + 1); 11 | int64_t cnt = 0; 12 | REP (i, n) { 13 | cnt += i - bit.initial_range_get(a[i] + 1); 14 | bit.point_mult(a[i], 1); 15 | } 16 | return cnt; 17 | } 18 | -------------------------------------------------------------------------------- /number/karatsuba.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | /** 7 | * @brief Karatsuba method ($O(n^{\log_2 3})$) 8 | */ 9 | template 10 | std::vector karatsuba_convolution(const std::vector & x, const std::vector & y) { 11 | int n = x.size(); 12 | int m = y.size(); 13 | if ((int64_t)n * m <= 100) { 14 | std::vector z(n + m - 1); 15 | REP (i, n) REP (j, m) { 16 | z[i + j] += x[i] * y[j]; 17 | } 18 | return z; 19 | } 20 | int half = (std::max(n, m) + 1) / 2; 21 | 22 | std::vector x0(x.begin(), x.begin() + std::min(n, half)); 23 | std::vector y0(y.begin(), y.begin() + std::min(m, half)); 24 | std::vector z0 = karatsuba_convolution(x0, y0); 25 | 26 | std::vector x1(x.begin() + std::min(n, half), x.end()); 27 | std::vector y1(y.begin() + std::min(m, half), y.end()); 28 | std::vector z2 = karatsuba_convolution(x1, y1); 29 | 30 | assert (x1.size() <= x0.size()); 31 | std::vector dx = x0; 32 | REP (i, x1.size()) dx[i] -= x1[i]; 33 | assert (y1.size() <= y0.size()); 34 | std::vector dy = y0; 35 | REP (i, y1.size()) dy[i] -= y1[i]; 36 | std::vector dz = karatsuba_convolution(dx, dy); 37 | 38 | std::vector z(n + m - 1); 39 | REP (i, z0.size()) { 40 | z[i] += z0[i]; 41 | if (half + i < (int)z.size()) z[half + i] += z0[i]; 42 | } 43 | REP (i, dz.size()) { 44 | if (half + i < (int)z.size()) z[half + i] -= dz[i]; 45 | } 46 | REP (i, z2.size()) { 47 | z[half + i] += z2[i]; 48 | if (2 * half + i < (int)z.size()) z[2 * half + i] += z2[i]; 49 | } 50 | return z; 51 | } 52 | -------------------------------------------------------------------------------- /number/matrix.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | template 7 | std::vector > operator * (const std::vector >& a, const std::vector >& b) { 8 | int n = a.size(); 9 | std::vector > c(n, std::vector(n)); 10 | REP (y, n) { 11 | REP (z, n) { 12 | REP (x, n) { 13 | c[y][x] += a[y][z] * b[z][x]; 14 | } 15 | } 16 | } 17 | return c; 18 | } 19 | 20 | template 21 | std::vector operator * (const std::vector >& a, const std::vector& b) { 22 | int n = a.size(); 23 | std::vector c(n); 24 | REP (y, n) { 25 | REP (z, n) { 26 | c[y] += a[y][z] * b[z]; 27 | } 28 | } 29 | return c; 30 | } 31 | 32 | template 33 | std::vector > unit_matrix(int n) { 34 | auto e = std::vector >(n, std::vector(n)); 35 | REP (i, n) { 36 | e[i][i] = 1; 37 | } 38 | return e; 39 | } 40 | 41 | template 42 | std::vector > zero_matrix(int n) { 43 | return std::vector >(n, std::vector(n)); 44 | } 45 | 46 | template 47 | std::vector > matpow(std::vector > x, int64_t y) { 48 | int n = x.size(); 49 | auto z = unit_matrix(n); 50 | for (int64_t i = 1; i <= y; i <<= 1) { 51 | if (y & i) { 52 | z = z * x; 53 | } 54 | x = x * x; 55 | } 56 | return z; 57 | } 58 | -------------------------------------------------------------------------------- /number/matrix.yukicoder-1073.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1073" 2 | #include "../number/matrix.hpp" 3 | #include "../modulus/mint.hpp" 4 | #include 5 | using namespace std; 6 | 7 | 8 | constexpr int MOD = 1000000007; 9 | mint solve(int64_t n) { 10 | vector > > f = { 11 | vector >{ 0, 0, 0, 0, 0, mint(6).inv() }, 12 | vector >{ 1, 0, 0, 0, 0, mint(6).inv() }, 13 | vector >{ 0, 1, 0, 0, 0, mint(6).inv() }, 14 | vector >{ 0, 0, 1, 0, 0, mint(6).inv() }, 15 | vector >{ 0, 0, 0, 1, 0, mint(6).inv() }, 16 | vector >{ 0, 0, 0, 0, 1, mint(6).inv() }, 17 | }; 18 | vector > x = { 19 | 0, 20 | 0, 21 | 0, 22 | 0, 23 | 0, 24 | 1, 25 | }; 26 | return (matpow(f, n) * x)[5]; 27 | } 28 | 29 | int main() { 30 | int64_t n; cin >> n; 31 | auto ans = solve(n); 32 | cout << ans << endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /number/matrix_template.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | template 7 | using matrix = std::array, H>; 8 | 9 | template 10 | matrix operator * (matrix const & a, matrix const & b) { 11 | matrix c = {}; 12 | REP (y, A) REP (z, B) REP (x, C) c[y][x] += a[y][z] * b[z][x]; 13 | return c; 14 | } 15 | template 16 | std::array operator * (matrix const & a, std::array const & b) { 17 | std::array c = {}; 18 | REP (y, H) REP (z, W) c[y] += a[y][z] * b[z]; 19 | return c; 20 | } 21 | 22 | template 23 | matrix operator + (matrix const & a, matrix const & b) { 24 | matrix c; 25 | REP (y, H) REP (x, W) c[y][x] = a[y][x] + b[y][x]; 26 | return c; 27 | } 28 | 29 | template 30 | std::array operator + (std::array const & a, std::array const & b) { 31 | std::array c; 32 | REP (i, N) c[i] = a[i] + b[i]; 33 | return c; 34 | } 35 | 36 | template 37 | matrix zero_matrix() { 38 | return {}; 39 | } 40 | 41 | template 42 | matrix unit_matrix() { 43 | matrix a = {}; 44 | REP (i, N) a[i][i] = 1; 45 | return a; 46 | } 47 | 48 | template 49 | matrix matpow(matrix x, int64_t k) { 50 | matrix y = unit_matrix(); 51 | for (; k; k >>= 1) { 52 | if (k & 1) y = y * x; 53 | x = x * x; 54 | } 55 | return y; 56 | } 57 | -------------------------------------------------------------------------------- /number/matrix_template.yukicoder-1073.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1073" 2 | #include "../number/matrix_template.hpp" 3 | #include "../modulus/mint.hpp" 4 | #include 5 | using namespace std; 6 | 7 | 8 | constexpr int MOD = 1000000007; 9 | mint solve(int64_t n) { 10 | matrix, 6, 6> f = {{ 11 | {{ 0, 0, 0, 0, 0, mint(6).inv() }}, 12 | {{ 1, 0, 0, 0, 0, mint(6).inv() }}, 13 | {{ 0, 1, 0, 0, 0, mint(6).inv() }}, 14 | {{ 0, 0, 1, 0, 0, mint(6).inv() }}, 15 | {{ 0, 0, 0, 1, 0, mint(6).inv() }}, 16 | {{ 0, 0, 0, 0, 1, mint(6).inv() }}, 17 | }}; 18 | array, 6> x = {{ 19 | 0, 20 | 0, 21 | 0, 22 | 0, 23 | 0, 24 | 1, 25 | }}; 26 | return (matpow(f, n) * x)[5]; 27 | } 28 | 29 | int main() { 30 | int64_t n; cin >> n; 31 | auto ans = solve(n); 32 | cout << ans << endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /number/miller-rabin.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | #include "../modulus/modpow.hpp" 6 | 7 | /** 8 | * @brief miller-rabin primality test 9 | * @note $O(k \log n)$ 10 | */ 11 | template 12 | bool is_prime(int64_t n, int iteration, RandomEngine& gen) { 13 | assert (0 <= n); 14 | if (n == 2) return true; 15 | if (n == 1 or n % 2 == 0) return false; 16 | const int64_t d = (n - 1) >> __builtin_ctzll(n - 1); // remove trailing zeros 17 | std::uniform_int_distribution dist(1, n - 2); // [l, r] 18 | REP (dummy, iteration) { 19 | int64_t a = dist(gen); 20 | int64_t t = d; 21 | int64_t y = modpow(a, t, n); 22 | while (t != n - 1 and y != 1 and y != n - 1) { 23 | y = y * y % n; 24 | t *= 2; 25 | } 26 | if (y != n - 1 and t % 2 == 0) return false; 27 | } 28 | return true; 29 | } 30 | 31 | bool is_prime(int64_t n) { 32 | static std::default_random_engine gen = std::default_random_engine(std::random_device()()); 33 | return is_prime(n, 20, gen); 34 | } 35 | -------------------------------------------------------------------------------- /number/primes.aoj.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_1_C" 2 | #include "../number/primes.hpp" 3 | #include 4 | #include 5 | 6 | int main() { 7 | int n; scanf("%d", &n); 8 | prepared_primes primes(1e6 + 3); 9 | int cnt = 0; 10 | REP (i, n) { 11 | int a; scanf("%d", &a); 12 | cnt += primes.is_prime(a); 13 | } 14 | printf("%d\n", cnt); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /number/primes.yukicoder-1140.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1140" 2 | #include 3 | #include "../utils/macros.hpp" 4 | #include "../number/primes.hpp" 5 | 6 | prepared_primes primes(1e6 + 100); 7 | 8 | int solve(long long a, int p) { 9 | if (not primes.is_prime(p)) return -1; 10 | if (a % p == 0) return 0; 11 | return 1; 12 | } 13 | 14 | int main() { 15 | int t; scanf("%d", &t); 16 | while (t --) { 17 | long long a; int p; scanf("%lld%d", &a, &p); 18 | auto ans = solve(a, p); 19 | printf("%d\n", ans); 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /number/primes_extra.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../utils/macros.hpp" 6 | #include "../number/primes.hpp" 7 | 8 | std::map list_prime_factors_as_map(const prepared_primes& primes, int64_t n) { 9 | std::map cnt; 10 | for (int64_t p : primes.list_prime_factors(n)) { 11 | ++ cnt[p]; 12 | } 13 | return cnt; 14 | } 15 | 16 | int64_t euler_totient(const prepared_primes& primes, int64_t n) { 17 | int64_t phi = 1; 18 | int64_t last = -1; 19 | for (int64_t p : primes.list_prime_factors(n)) { 20 | if (last != p) { 21 | last = p; 22 | phi *= p - 1; 23 | } else { 24 | phi *= p; 25 | } 26 | } 27 | return phi; 28 | } 29 | -------------------------------------------------------------------------------- /number/primes_extra.yukicoder-1659.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1659" 2 | #include 3 | #include "../utils/macros.hpp" 4 | #include "../modulus/mint.hpp" 5 | #include "../number/primes.hpp" 6 | #include "../number/primes_extra.hpp" 7 | #include "../modulus/multichoose_simple.hpp" 8 | using namespace std; 9 | 10 | prepared_primes primes(1e6 + 100); 11 | 12 | constexpr int64_t MOD = 1000000007; 13 | mint solve(int64_t n, int64_t k) { 14 | mint ans = 1; 15 | for (auto [p, e] : list_prime_factors_as_map(primes, n)) { 16 | // ans *= multichoose_simple(k, e); 17 | mint y = 0; 18 | REP (x, e + 1) { 19 | y += multichoose_simple(k, x); 20 | } 21 | ans *= y; 22 | } 23 | return ans; 24 | } 25 | 26 | // generated by oj-template v4.8.0 (https://github.com/online-judge-tools/template-generator) 27 | int main() { 28 | std::ios::sync_with_stdio(false); 29 | std::cin.tie(nullptr); 30 | int64_t N, K; 31 | std::cin >> N >> K; 32 | auto ans = solve(N, K); 33 | std::cout << ans << '\n'; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /old/bernoulli-number.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief the Bernoulli number 3 | * @tparam MOD must be a prime 4 | * @note $O(n^2)$ 5 | * @see https://ja.wikipedia.org/wiki/%E3%83%99%E3%83%AB%E3%83%8C%E3%83%BC%E3%82%A4%E6%95%B0 6 | */ 7 | template 8 | int bernoulli_number(int i) { 9 | static vector dp(1, 1); 10 | while (dp.size() <= i) { 11 | int n = dp.size(); 12 | ll acc = 0; 13 | REP (k, n) { 14 | acc += choose(n + 1, k) *(ll) dp[k] % MOD; 15 | } 16 | acc %= MOD; 17 | (acc *= modinv(n + 1, MOD)) %= MOD; 18 | acc = (acc == 0 ? 0 : MOD - acc); 19 | dp.push_back(acc); 20 | } 21 | return dp[i]; 22 | } 23 | unittest { 24 | constexpr int MOD = 1e9 + 7; 25 | assert (bernoulli_number(0) == 1); 26 | assert (bernoulli_number(1) == (MOD - 1ll) * modinv(2, MOD) % MOD); 27 | assert (bernoulli_number(2) == modinv(6, MOD)); 28 | assert (bernoulli_number(3) == 0); 29 | assert (bernoulli_number(4) == (MOD - 1ll) * modinv(30, MOD) % MOD); 30 | assert (bernoulli_number(26) == 8553103ll * modinv(6, MOD) % MOD); 31 | } 32 | 33 | /** 34 | * @brief $0^k + 1^k + 2^k + ... + (n - 1)^k$ 35 | * @see https://yukicoder.me/problems/no/665 36 | * @note n can be >= MOD 37 | */ 38 | template 39 | int sum_of_pow(ll n, int k) { 40 | ll acc = 0; 41 | REP (j, k + 1) { 42 | acc += choose(k + 1, j) *(ll) bernoulli_number(j) % MOD *(ll) powmod(n % MOD, k - j + 1, MOD) % MOD; 43 | } 44 | acc %= MOD; 45 | (acc *= modinv(k + 1, MOD)) %= MOD; 46 | return acc; 47 | } 48 | -------------------------------------------------------------------------------- /old/bipartite-graph.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @note g must be connected 3 | * @return is the size of a part 4 | */ 5 | int check_bipartite_graph(vector > const & g) { 6 | int n = g.size(); 7 | vector used(n, -1); 8 | function dfs = [&](int i, int parent) { 9 | for (int j : g[i]) { 10 | if (used[j] != -1) { 11 | if (used[j] == used[i]) { 12 | return false; 13 | } 14 | } else { 15 | used[j] = used[i] ^ 1; 16 | if (not dfs(j, i)) return false; 17 | } 18 | } 19 | return true; 20 | }; 21 | used[0] = 0; 22 | if (not dfs(0, -1)) return -1; 23 | return count(whole(used), 0); 24 | } 25 | -------------------------------------------------------------------------------- /old/boyer-moore.inc.cpp: -------------------------------------------------------------------------------- 1 | array bm_build_skip(string const & pattern) { // O(m) 2 | int m = pattern.length(); 3 | array skip = {}; 4 | repeat (i,m) skip[pattern[i]-'a'] = m-i-1; 5 | return skip; 6 | } 7 | vector bm_build_next(string const & pattern) { // O(m) 8 | int m = pattern.length(); 9 | int g[m]; fill(g, g+m, m); 10 | vector next(m); 11 | repeat (i,m) next[i] = 2*m-i-1; 12 | int j = m; 13 | for (int i = m-1; i >= 0; --i, --j) { 14 | g[i] = j; 15 | while (j < m and pattern[j] != pattern[i]) { 16 | next[j] = min(next[j], m-i-1); 17 | j = g[j]; 18 | } 19 | } 20 | repeat (i,m) { 21 | next[i] = min(next[i], j+m-i); 22 | if (i >= j) j = g[j]; 23 | } 24 | return next; 25 | } 26 | int bm_match(string const & target, string const & pattern, array const & skip, vector const & next) { // O(nm) 27 | int n = target.length(); 28 | int m = pattern.length(); 29 | int result = 0; 30 | for (int i = m-1; i < n; ) { 31 | int j = m-1; 32 | while (j >= 0 and target[i] == pattern[j]) { --i; --j; } 33 | if (j < 0) { 34 | ++ result; // match at text[i+1, ..., i+m] 35 | i += m + 1; 36 | } else { 37 | i += max(skip[target[i]-'a'], next[j]); 38 | } 39 | } 40 | return result; 41 | } 42 | int bm_match(string const & target, string const & pattern) { // Boyer-Moore 43 | return bm_match(target, pattern, bm_build_skip(pattern), bm_build_next(pattern)); 44 | } 45 | -------------------------------------------------------------------------------- /old/breadth-first-search.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief compute the distances from root 3 | * @note O(n) 4 | * @arg g is a digraph 5 | * @note loops and double edges are allowed 6 | */ 7 | vector breadth_first_search(int root, vector > const & g) { 8 | int n = g.size(); 9 | vector dist(n, INT_MAX); 10 | queue que; 11 | dist[root] = 0; 12 | que.push(root); 13 | while (not que.empty()) { 14 | int i = que.front(); que.pop(); 15 | for (int j : g[i]) if (dist[j] == INT_MAX) { 16 | dist[j] = dist[i] + 1; 17 | que.push(j); 18 | } 19 | } 20 | return dist; 21 | } 22 | 23 | /** 24 | * @brief 0-1 BFS 25 | * @arg g is a weighted digraph whose weights are 0 or 1 26 | * @note loops and double edges are allowed 27 | */ 28 | vector zero_one_breadth_first_search(int root, vector > > const & g) { 29 | int n = g.size(); 30 | vector dist(n, INT_MAX); 31 | deque > que; 32 | dist[root] = 0; 33 | que.emplace_back(root, dist[root]); 34 | while (not que.empty()) { 35 | int i, dist_i; tie(i, dist_i) = que.front(); que.pop_front(); 36 | if (dist[i] < dist_i) continue; 37 | for (auto edge : g[i]) { 38 | int j; bool cost; tie(j, cost) = edge; 39 | if (dist[i] + cost < dist[j]) { 40 | dist[j] = dist[i] + cost; 41 | if (cost) { 42 | que.emplace_back(j, dist[j]); 43 | } else { 44 | que.emplace_front(j, dist[j]); 45 | } 46 | } 47 | } 48 | } 49 | return dist; 50 | } 51 | -------------------------------------------------------------------------------- /old/centers.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief get centers of a tree / 木の中心 3 | */ 4 | vector get_centers(vector > const & tree) { 5 | int n = tree.size(); 6 | vector used(n); 7 | vector cur, prv; 8 | REP (i, n) { 9 | if (tree[i].size() <= 1) { 10 | cur.push_back(i); 11 | used[i] = true; 12 | } 13 | } 14 | while (not cur.empty()) { 15 | cur.swap(prv); 16 | cur.clear(); 17 | for (int i : prv) { 18 | for (int j : tree[i]) if (not used[j]) { 19 | cur.push_back(j); 20 | used[j] = true; 21 | } 22 | } 23 | } 24 | return prv; 25 | } 26 | -------------------------------------------------------------------------------- /old/centroid-decomposition.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief get centroids of a graph / 重心分解 3 | * @note O(n) time 4 | * @note O(n) space on heap 5 | * @return the size is 1 or 2 6 | */ 7 | vector get_centroids(vector > const & g, int root, set const & forbidden) { 8 | map available; { 9 | function go = [&](int i, int parent) { 10 | available.emplace(i, available.size()); 11 | for (auto j : g[i]) if (j != parent and not forbidden.count(j)) { 12 | go(j, i); 13 | } 14 | }; 15 | go(root, -1); 16 | } 17 | int n = available.size(); 18 | vector result; 19 | vector size(n, -1); 20 | function go = [&](int x, int parent) { 21 | bool is_centroid = true; 22 | int i = available[x]; 23 | size[i] = 1; 24 | for (auto y : g[x]) if (y != parent and available.count(y)) { 25 | int j = available[y]; 26 | go(y, x); 27 | size[i] += size[j]; 28 | if (size[j] > n / 2) is_centroid = false; 29 | } 30 | if (n - size[i] > n / 2) is_centroid = false; 31 | if (is_centroid) result.push_back(x); 32 | }; 33 | go(root, -1); 34 | return result; 35 | } 36 | -------------------------------------------------------------------------------- /old/convex-hull.inc.cpp: -------------------------------------------------------------------------------- 1 | double dot(complex a, complex b) { return real(a * conj(b)); } 2 | double cross(complex a, complex b) { return imag(conj(a) * b); } 3 | int ccw(complex a, complex b, complex c) { 4 | b -= a; 5 | c -= a; 6 | if (cross(b, c) > 0) return +1; // counter clockwise 7 | if (cross(b, c) < 0) return -1; // clockwise 8 | if (dot(b, c) < 0) return +2; // c--a--b on line 9 | if (abs(b) < abs(c)) return -2; // a--b--c on line 10 | return 0; 11 | } 12 | /** 13 | * @see http://www.prefield.com/algorithm/geometry/convex_hull.html 14 | */ 15 | vector > convex_hull(vector > ps) { 16 | int n = ps.size(); 17 | if (n <= 2) return ps; 18 | int k = 0; 19 | sort(ps.begin(), ps.end(), [&](complex const a, complex const b) { return make_pair(a.real(), a.imag()) < make_pair(b.real(), b.imag()); }); 20 | vector > ch(2 * n); 21 | for (int i = 0; i < n; ch[k ++] = ps[i ++]) { // lower-hull 22 | while (k >= 2 and ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) -- k; 23 | } 24 | for (int i = n - 2, t = k + 1; i >= 0; ch[k ++] = ps[i --]) { // upper-hull 25 | while (k >= t and ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) -- k; 26 | } 27 | ch.resize(k - 1); 28 | return ch; 29 | } 30 | -------------------------------------------------------------------------------- /old/dice.inc.cpp: -------------------------------------------------------------------------------- 1 | struct dice_t { // regular hexahedron group 2 | // ______ 3 | // \ \ 4 4 | // / \ C \ 2156 5 | // / A \______\ 3 ^ 6 | // \ A / B / ^^ | 7 | // \ / B / ab bottom 8 | // v__B___/ 9 | int a, b; // in [1, 6] 10 | int c() const { 11 | static const int table[6][6] = { 12 | { 0, 3, 5, 2, 4, 0 }, 13 | { 4, 0, 1, 6, 0, 3 }, 14 | { 2, 6, 0, 0, 1, 5 }, 15 | { 5, 1, 0, 0, 6, 2 }, 16 | { 3, 0, 6, 1, 0, 4 }, 17 | { 0, 4, 2, 5, 3, 0 }, 18 | }; 19 | assert (table[a-1][b-1] != 0); 20 | return table[a-1][b-1]; 21 | } 22 | }; 23 | dice_t rotate_up( dice_t dice) { return (dice_t) { dice.a, 7 - dice.c() }; } 24 | dice_t rotate_right(dice_t dice) { return (dice_t) { 7 - dice.c(), dice.b }; } 25 | dice_t rotate_down( dice_t dice) { return (dice_t) { dice.a, dice.c() }; } 26 | dice_t rotate_left( dice_t dice) { return (dice_t) { dice.c(), dice.b }; } 27 | bool operator == (dice_t x, dice_t y) { return x.a == y.a and x.b == y.b; } 28 | -------------------------------------------------------------------------------- /old/digit-dp.inc.cpp: -------------------------------------------------------------------------------- 1 | // http://yukicoder.me/problems/no/260 2 | // strmodin(s, a, b, m)[i][j] = the number of digits t in mod m for t \le s, i = t \bmod \prod a and t contains digits j \subset b 3 | vector > strmodin(string const & s, int a, vector const & b, ll m) { 4 | int pow_b = 1 << b.size(); 5 | array table = {}; 6 | repeat (d,10) { 7 | auto it = whole(find, b, d); 8 | if (it != b.end()) table[d] |= 1 << (it - b.begin()); 9 | } 10 | auto cur = vectors(a, pow_b, ll()); 11 | auto prv = vectors(a, pow_b, ll()); 12 | int bound_i = 0, bound_j = 0; 13 | for (char c : s) { 14 | c -= '0'; 15 | cur.swap(prv); 16 | repeat (d, c) cur[(bound_i * 10 + d) % a][bound_j | table[d]] += 1; 17 | bound_i = (bound_i * 10 + c) % a; 18 | bound_j |= table[c]; 19 | repeat (i,a) repeat (j,pow_b) { 20 | repeat (d,10) { 21 | ll & it = cur[(i * 10 + d) % a][j | table[d]]; 22 | it = (it + prv[i][j]) % m; 23 | } 24 | prv[i][j] = 0; 25 | } 26 | } 27 | cur[bound_i][bound_j] += 1; 28 | cur[bound_i][bound_j] %= m; 29 | return cur; 30 | } 31 | -------------------------------------------------------------------------------- /old/distributed-code-jam.inc.cpp: -------------------------------------------------------------------------------- 1 | template void PutGeneric(int target, T value); 2 | template <> void PutGeneric(int target, char value) { PutChar(target, value); } 3 | template <> void PutGeneric(int target, int value) { PutInt(target, value); } 4 | template <> void PutGeneric(int target, long long value) { PutLL(target, value); } 5 | 6 | template 7 | void PutVec(int target, Container & values) { 8 | PutInt(target, values.size()); 9 | for (auto value : values) PutGeneric(target, value); 10 | } 11 | 12 | template T GetGeneric(int source); 13 | template <> char GetGeneric(int source) { return GetChar(source); } 14 | template <> int GetGeneric(int source) { return GetInt(source); } 15 | template <> long long GetGeneric(int source) { return GetLL(source); } 16 | 17 | template 18 | Container GetVec(int source) { 19 | int size = GetInt(source); 20 | Container values; 21 | values.resize(size); 22 | repeat (i, size) values[i] = GetGeneric(source); 23 | return values; 24 | } 25 | -------------------------------------------------------------------------------- /old/doubling.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief the doubling technique 3 | */ 4 | struct doubling_table { 5 | vector > table; 6 | doubling_table() = default; 7 | /** 8 | * @note O(N log K) 9 | */ 10 | doubling_table(vector const & next, int size = -1) { 11 | int n = next.size(); 12 | { 13 | auto it = minmax_element(ALL(next)); 14 | assert (0 <= *(it.first) and *(it.second) <= n); 15 | } 16 | if (size == -1) { 17 | size = max(1, ceil(log2(n))); 18 | } 19 | table.resize(size); 20 | table[0] = next; 21 | REP (k, size - 1) { 22 | table[k + 1].resize(n, n); 23 | REP (i, n) if (table[k][i] != n) { 24 | table[k + 1][i] = table[k][table[k][i]]; 25 | } 26 | } 27 | } 28 | /** 29 | * @note O(log K) 30 | */ 31 | int get(int i, int count) { 32 | assert (count < (1 << table.size())); 33 | int n = table[0].size(); 34 | if (i == n) return n; 35 | assert (0 <= i and i < n); 36 | REP_R (k, table.size()) if (count & (1 << k)) { 37 | i = table[k][i]; 38 | if (i == n) return n; 39 | } 40 | return i; 41 | } 42 | }; 43 | 44 | unittest { 45 | vector step { 1, 3, 3, 4, 5, 6, 8, 8, 9, 10 }; 46 | doubling_table steps(step); 47 | assert (steps.get(6, 2) == step[step[6]]); 48 | assert (steps.get(3, 5) == step[step[step[step[step[3]]]]]); 49 | } 50 | -------------------------------------------------------------------------------- /old/factoradic.inc.cpp: -------------------------------------------------------------------------------- 1 | template 2 | uint64_t encode_factoradic(RandomAccessIterator first, RandomAccessIterator last) { // O(N^2) 3 | static vector fact(1, 1); 4 | while (fact.size() < n) { 5 | fact.push_back(fact.size() * fact.back()); 6 | } 7 | int n = last - first; 8 | uint64_t y = 0; 9 | REP (i, n) { 10 | int xi = *(first + i); 11 | int rank = count_if(first, first + i, [&](int xj) { return xi < xj; }); 12 | y += rank * fact[i]; 13 | } 14 | return y; 15 | } 16 | vector decode_factoradic(uint64_t y, int n) { // O(N^2) 17 | static vector fact(1, 1); 18 | while (fact.size() < n) { 19 | fact.push_back(fact.size() * fact.back()); 20 | } 21 | vector xs(n); 22 | vector zs(n); iota(zs.begin(), zs.end(), 0); 23 | REP_R (i, n) { 24 | auto it = zs.begin() + (i - y / fact[i]); 25 | xs[i] = *it; 26 | zs.erase(it); 27 | y %= fact[i]; 28 | } 29 | return xs; 30 | } 31 | -------------------------------------------------------------------------------- /old/graphviz.inc.cpp: -------------------------------------------------------------------------------- 1 | void graphviz(vector > const & g, bool is_digraph = false, string const & name = "graph") { 2 | ofstream ofs(name + ".dot"); 3 | ofs << (is_digraph ? "di" : "") << "graph graph_name {" << endl; 4 | ofs << " graph [ bgcolor = \"#00000000\" ]" << endl; 5 | ofs << " node [ shape = circle, style = filled, fillcolor = \"#ffffffff\" ]" << endl; 6 | REP (i, g.size()) for (int j : g[i]) if (is_digraph or i <= j) ofs << " " << i << (is_digraph ? " -> " : " -- ") << j << endl; 7 | ofs << "}" << endl; 8 | ofs.close(); 9 | system(("dot -T png " + name + ".dot > " + name + ".png").c_str()); 10 | } 11 | -------------------------------------------------------------------------------- /old/iterate.inc.cpp: -------------------------------------------------------------------------------- 1 | // http://yukicoder.me/submissions/142657 2 | struct sequence { 3 | vector data; 4 | int offset, cycle; 5 | }; 6 | sequence iterate(int a, function f) { 7 | sequence xs; 8 | map used; 9 | while (not used.count(a)) { 10 | used[a] = xs.data.size(); 11 | xs.data.push_back(a); 12 | a = f(a); 13 | } 14 | xs.offset = used[a]; 15 | xs.cycle = xs.data.size() - xs.offset; 16 | return xs; 17 | } 18 | int at(sequence const & xs, int i) { 19 | return xs.data[i < xs.offset ? i : (i - xs.offset) % xs.cycle + xs.offset]; 20 | } 21 | -------------------------------------------------------------------------------- /old/knapsack-problem-branch-and-bound.inc.cpp: -------------------------------------------------------------------------------- 1 | ll knapsack_problem_branch_and_bound(int n, ll max_w, vector const & a_v, vector const & a_w) { 2 | vector v(n), w(n); { 3 | vector xs(n); 4 | iota(ALL(xs), 0); 5 | sort(ALL(xs), [&](int i, int j) { 6 | return a_v[i] *(double) a_w[j] > a_v[j] *(double) a_w[i]; 7 | }); 8 | REP (i, n) { 9 | v[i] = a_v[xs[i]]; 10 | w[i] = a_w[xs[i]]; 11 | } 12 | } 13 | ll ans = 0; 14 | function go = [&](int i, ll cur_v, ll cur_w) { 15 | if (max_w < cur_w) return; // not executable 16 | if (i == n) { 17 | chmax(ans, cur_v); 18 | return; // terminate 19 | } 20 | ll lr_v = cur_v; // linear relaxation 21 | ll lr_w = cur_w; 22 | int j = i; 23 | for (; j < n and lr_w + w[j] <= max_w; ++ j) { // greedy 24 | lr_w += w[j]; 25 | lr_v += v[j]; 26 | } 27 | if (lr_w == max_w or j == n) { 28 | chmax(ans, lr_v); 29 | return; // accept greedy 30 | } 31 | double lr_ans = lr_v + v[j] * ((max_w - lr_w) /(double) w[j]); 32 | if (lr_ans <= ans) return; // bound 33 | go(i + 1, cur_v + v[i], cur_w + w[i]); 34 | go(i + 1, cur_v, cur_w ); 35 | }; 36 | go(0, 0, 0); 37 | return ans; 38 | } 39 | -------------------------------------------------------------------------------- /old/knuth-morris-pratt.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Morris-Pratt algorithm 3 | * @description compute the list of the lengthes of the longest borders 4 | * @note O(N) 5 | */ 6 | template 7 | vector morris_pratt(Iterator first, Iterator last) { 8 | int length = distance(first, last); 9 | vector border(length + 1); 10 | border[0] = -1; 11 | int j = -1; 12 | REP (i, length) { 13 | while (j >= 0 and pattern[i] != pattern[j]) { 14 | j = border[j]; 15 | } 16 | ++ j; 17 | border[i + 1] = j; 18 | } 19 | return border; 20 | } 21 | 22 | /* 23 | vector kmp_build_fail(string const & pattern) { // O(m) 24 | int m = pattern.size(); 25 | vector fali(m+1); 26 | fail[0] = -1; 27 | int j = -1; 28 | repeat (i,m) { 29 | while (j >= 0 and pattern[i] != pattern[j]) j = fail[j]; 30 | fail[i+1] = ++ j; 31 | } 32 | return fail; 33 | } 34 | int kmp_match(string const & target, string const & pattern, vector const & fail) { // O(n+m) 35 | int n = target.length(); 36 | int m = pattern.length(); 37 | int result = 0; 38 | for (int i = 0, k = 0; i < n; ++ i) { 39 | while (k >= 0 and pattern[k] != target[i]) k = fail[k]; 40 | if (++ k >= m) { 41 | ++ result; // match at t[i-m+1 .. i] 42 | k = fail[k]; 43 | } 44 | } 45 | return result; 46 | } 47 | int kmp_match(string const & target, string const & pattern) { 48 | return kmp_match(target, pattern, kmp_build_fail(pattern)); 49 | } 50 | */ 51 | -------------------------------------------------------------------------------- /old/longest-increasing-subsequence.inc.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector longest_strict_increasing_subsequence(vector const & xs) { 3 | vector l; // l[i] is the last element of the increasing subsequence whose length is i + 1 4 | l.push_back(xs.front()); 5 | for (auto && x : xs) { 6 | auto it = lower_bound(l.begin(), l.end(), x); 7 | if (it == l.end()) { 8 | l.push_back(x); 9 | } else { 10 | *it = x; 11 | } 12 | } 13 | return l; 14 | } 15 | 16 | template 17 | vector longest_weak_increasing_subsequence(vector const & xs) { 18 | vector l; 19 | for (auto && x : xs) { 20 | auto it = upper_bound(l.begin(), l.end(), x); 21 | if (it == l.end()) { 22 | l.push_back(x); 23 | } else { 24 | *it = x; 25 | } 26 | } 27 | return l; 28 | } 29 | -------------------------------------------------------------------------------- /old/maximum-independent-set.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://www.slideshare.net/wata_orz/ss-12131479 3 | * @note O(1.466^n n) 4 | * @param g is an adjacency matrix 5 | */ 6 | int maximum_independent_set(vector > const & g) { 7 | int n = g.size(); 8 | function const &)> go = [&](int i, vector used) { 9 | while (i < n and used[i]) ++ i; 10 | if (i == n) return 0; 11 | int degree = 0; 12 | repeat_from (j, i + 1, n) { 13 | degree += (not used[j] and g[i][j]); 14 | } 15 | int result = 0; 16 | used[i] = true; 17 | if (degree >= 2) { 18 | setmax(result, go(i + 1, used)); // don't use i 19 | } 20 | repeat_from (j, i + 1, n) { 21 | used[j] = (used[j] or g[i][j]); 22 | } 23 | setmax(result, 1 + go(i + 1, used)); // use i 24 | return result; 25 | }; 26 | return go(0, vector(n)); 27 | } 28 | -------------------------------------------------------------------------------- /old/midpoint.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief a structure to make a midpoint for given two points 3 | */ 4 | class midpoint { 5 | vector data; 6 | midpoint(vector const & data_) : data(data_) {} 7 | public: 8 | midpoint() : data({ false, true }) {} 9 | static midpoint min() { return midpoint(vector()); } 10 | static midpoint max() { return midpoint(vector(1, true)); } 11 | /** 12 | * @brief for given $a$ and $c$, make $b$ s.t. $a < b < c$ 13 | */ 14 | midpoint between(midpoint const & other) const { 15 | auto const & a = this->data; 16 | auto const & b = other.data; 17 | vector c(::max(a.size(), b.size()) + 1); 18 | bool is_carried = false; 19 | REP_R (i, ::max(a.size(), b.size())) { 20 | bool a_i = (i < a.size() and a[i]); 21 | bool b_i = (i < b.size() and b[i]); 22 | c[i + 1] = a_i ^ b_i ^ is_carried; 23 | is_carried = a_i + b_i + is_carried >= 2; 24 | } 25 | c[0] = is_carried; 26 | while (not c.empty() and not c.back()) { 27 | c.pop_back(); 28 | } 29 | return midpoint(c); 30 | } 31 | bool operator < (midpoint const & other) const { 32 | return this->data < other.data; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /old/periodic-function-power.inc.cpp: -------------------------------------------------------------------------------- 1 | template 2 | T periodic_function_power(F f, ll k, T x) { 3 | assert (k >= 1); 4 | if (k == 1) return x; 5 | vector history; 6 | unordered_map lookup; 7 | history.push_back(x); 8 | lookup[x] = 0; 9 | for (int i = 1; ; ++ i) { 10 | T y = f(x); 11 | if (i == k) return y; 12 | if (lookup.count(y)) break; 13 | history.push_back(y); 14 | lookup[y] = lookup[x] + 1; 15 | x = y; 16 | } 17 | T y = f(x); 18 | int base = lookup[y]; 19 | int cycle = lookup[x] + 1 - lookup[y]; 20 | return history[(k - base) % cycle + base]; 21 | } 22 | -------------------------------------------------------------------------------- /old/point-int.inc.cpp: -------------------------------------------------------------------------------- 1 | struct point_t { ll y, x; }; 2 | point_t operator + (point_t a, point_t b) { return { a.y + b.y, a.x + b.x }; } 3 | point_t operator - (point_t a, point_t b) { return { a.y - b.y, a.x - b.x }; } 4 | point_t operator - (point_t a) { return { - a.y, - a.x }; } 5 | point_t operator * (ll a, point_t b) { return { a * b.y, a * b.x }; } 6 | std::pair to_pair(point_t a) { return { a.y, a.x }; } 7 | bool operator == (point_t a, point_t b) { return to_pair(a) == to_pair(b); } 8 | bool operator != (point_t a, point_t b) { return to_pair(a) != to_pair(b); } 9 | bool operator < (point_t a, point_t b) { return to_pair(a) < to_pair(b); } 10 | bool operator <= (point_t a, point_t b) { return to_pair(a) <= to_pair(b); } 11 | bool operator >= (point_t a, point_t b) { return to_pair(a) >= to_pair(b); } 12 | bool operator > (point_t a, point_t b) { return to_pair(a) > to_pair(b); } 13 | ll length_squared(point_t p) { return p.y*p.y + p.x*p.x; } 14 | ll length(point_t p) { return sqrt(length_squared(p)); } 15 | point_t normalized(point_t a) { return (1.0 / length(a)) * a; } 16 | ll dot(point_t p, point_t q) { return p.x * q.x + p.y * q.y; } 17 | ll cross(point_t p, point_t q) { return p.x * q.y - p.y * q.x; } 18 | int ccw(point_t a, point_t b, point_t c) { ll z = cross(b - a, c - a); return z > 0 ? 1 : z < 0 ? -1 : 0; } 19 | std::istream & operator >> (std::istream & in, point_t & a) { return in >> a.x >> a.y; } 20 | std::ostream & operator << (std::ostream & out, point_t a) { return out << a.x << ' ' << a.y; } 21 | 22 | function make_is_on_field(point_t p) { return [=](point_t q) { return 0 <= q.y and q.y < p.y and 0 <= q.x and q.x < p.x; }; } 23 | const point_t directions[4] = { { -1, 0 }, { 1, 0 }, { 0, 1 }, { 0, -1 } }; 24 | -------------------------------------------------------------------------------- /old/polya-enumeration.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @note using Polya enumeration theorem 3 | * @note factorization + O(d(n)^2 + sqrt n) 4 | */ 5 | template 6 | mint count_cycle_coloring(int n, int k) { 7 | auto primes = list_primes(sqrt(n) + 3); 8 | map factors = prime_factorize(n, primes); 9 | vector divs = list_divisors(n, primes); 10 | mint cnt = 0; 11 | for (ll div : divs) { 12 | ll e = div; // Euler's phi of div 13 | for (auto it : factors) { 14 | int p = it.first; 15 | if (div % p == 0) { 16 | e = e / p * (p - 1); 17 | } 18 | } 19 | cnt += mint(k).pow(n / div) * e; 20 | } 21 | return cnt / n; 22 | } 23 | 24 | unittest { 25 | constexpr int MOD = 1e9 + 7; 26 | assert (count_cycle_coloring(2, 10).value == 55); 27 | assert (count_cycle_coloring(4, 10).value == 2530); 28 | assert (count_cycle_coloring(4, 2).value == 6); 29 | assert (count_cycle_coloring(1000000000, 1000000000).value == 898487047); 30 | } 31 | -------------------------------------------------------------------------------- /old/popen2.inc.cpp: -------------------------------------------------------------------------------- 1 | pid_t popen2(const char *command, int *fd_r, int *fd_w) { 2 | constexpr int READ = 0; 3 | constexpr int WRITE = 1; 4 | int p_stdin[2], p_stdout[2]; 5 | if (pipe(p_stdin) != 0 or pipe(p_stdout) != 0) return -1; 6 | pid_t pid = fork(); 7 | if (pid < 0) return -1; 8 | if (pid == 0) { 9 | close(p_stdin[WRITE]); 10 | dup2(p_stdin[READ], STDIN_FILENO); 11 | close(p_stdout[READ]); 12 | dup2(p_stdout[WRITE], STDOUT_FILENO); 13 | execl("/bin/sh", "sh", "-c", command, NULL); 14 | exit(1); 15 | } else { 16 | if (fd_r == NULL) { 17 | close(p_stdin[WRITE]); 18 | } else { 19 | *fd_r = p_stdin[WRITE]; 20 | } 21 | if (fd_w == NULL) { 22 | close(p_stdout[READ]); 23 | } else { 24 | *fd_w = p_stdout[READ]; 25 | } 26 | return pid; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /old/range-union-find-tree.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @note 計算量は確かに落ちるのだけどこれを使って速くなるケースは元々全部連結してて自明な気がする 3 | * @note thank to https://beta.atcoder.jp/contests/yahoo-procon2018-final/submissions/2126707 4 | */ 5 | struct range_union_find_tree { 6 | vector data; 7 | range_union_find_tree() = default; 8 | explicit range_union_find_tree(size_t n) { 9 | int log_n = 32 - __builtin_clz(n); 10 | data.resize(log_n, union_find_tree(n)); 11 | } 12 | /** 13 | * @description unite (l1 + k)-th tree and (l2 + k)-th tree for each k in [0, len) 14 | * @note O(1) 15 | */ 16 | void range_unite_trees(int l1, int l2, int len) { 17 | int n = data.front().data.size(); 18 | assert (0 <= l1 and l1 + len <= n); 19 | assert (0 <= l2 and l2 + len <= n); 20 | assert (len >= 1); 21 | int k = 31 - __builtin_clz(len); // log2 22 | data[k].unite_trees(l1, l2); 23 | data[k].unite_trees(l1 + len - (1 << k), l2 + len - (1 << k)); 24 | } 25 | /** 26 | * @description collapse range-queries and get result 27 | * @note O(N \log N) 28 | */ 29 | union_find_tree const & update() { 30 | int n = data.front().data.size(); 31 | int log_n = data.size(); 32 | REP_R (k, log_n - 1) { 33 | REP (i, n - (1 << k)) { 34 | int root = data[k + 1].find_root(i); 35 | data[k].unite_trees(i, root); 36 | data[k].unite_trees(i + (1 << k), root + (1 << k)); 37 | } 38 | } 39 | return data[0]; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /old/rational.inc.cpp: -------------------------------------------------------------------------------- 1 | struct rational { int num, den; }; 2 | rational make_rational(ll num, ll den = 1) { ll k = gcd(num, den); return (rational) { int(num / k), int(den / k) }; } 3 | rational operator + (rational a, rational b) { return make_rational(a.num *(ll) b.den + b.num *(ll) a.den, a.den *(ll) b.den); } 4 | rational operator - (rational a, rational b) { return make_rational(a.num *(ll) b.den - b.num *(ll) a.den, a.den *(ll) b.den); } 5 | rational operator * (rational a, rational b) { return make_rational(a.num *(ll) b.num, a.den *(ll) b.den); } 6 | rational operator / (rational a, rational b) { return make_rational(a.num *(ll) b.den, a.den *(ll) b.num); } 7 | bool operator < (rational a, rational b) { return a.num *(ll) b.den < b.num *(ll) a.den; } 8 | bool operator > (rational a, rational b) { return a.num *(ll) b.den > b.num *(ll) a.den; } 9 | bool operator == (rational a, rational b) { return a.num == b.num and a.den == b.den; } 10 | bool operator != (rational a, rational b) { return a.num != b.num or a.den != b.den; } 11 | ostream & operator << (ostream & out, rational a) { if (a.den == 0) return out << "invalid"; return out << a.num << '/' << a.den; } 12 | -------------------------------------------------------------------------------- /old/rollback-square-decomposition.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief the extended Mo's algorithm 3 | * @arg stupid is called O(Q) times, each length is O(\sqrt{N}) 4 | * @arg mo si the following: 5 | * struct rollback_mo_interface { 6 | * void reset(int l); // called O(N) times 7 | * void extend_left( int l, int r); // called O(Q) times, the sum of length is O(N \sqrt {N}) 8 | * void extend_right(int l, int r); // called O(Q) times, the sum of length is O(Q \sqrt {N}) 9 | * void snapshot(); // called O(Q) times 10 | * void rollback(); // called O(Q) times 11 | * void query(); // called O(Q) times 12 | * }; 13 | * @see http://snuke.hatenablog.com/entry/2016/07/01/000000 14 | * @see http://codeforces.com/blog/entry/7383?#comment-161520 15 | */ 16 | template 17 | void rollback_square_decomposition(int n, vector > const & range, RollbackMoInterface & mo, Func stupid) { 18 | int bucket_size = sqrt(n); 19 | int bucket_count = (n + bucket_size - 1) / bucket_size; 20 | vector > bucket(bucket_count); 21 | REP (i, int(range.size())) { 22 | int l, r; tie(l, r) = range[i]; 23 | if (r - l <= bucket_size) { 24 | stupid(l, r); 25 | } else { 26 | bucket[l / bucket_size].push_back(i); 27 | } 28 | } 29 | REP (b, bucket_count) { 30 | sort(ALL(bucket[b]), [&](int i, int j) { return range[i].second < range[j].second; }); 31 | int l = (b + 1) * bucket_size; 32 | mo.reset(l); 33 | int r = l; 34 | for (int i : bucket[b]) { 35 | int l_i, r_i; tie(l_i, r_i) = range[i]; 36 | mo.extend_right(r, r_i); 37 | mo.snapshot(); 38 | mo.extend_left(l_i, l); 39 | mo.query(); 40 | mo.rollback(); 41 | r = r_i; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /old/sliding-window.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief the sliding window minimum algorithm 3 | * @note to get maximums, use greater 4 | * @note verified http://poj.org/problem?id=2823 5 | * @note verified http://cf16-tournament-round3-open.contest.atcoder.jp/tasks/asaporo_d 6 | */ 7 | template > 8 | class sliding_window { 9 | deque > data; 10 | Compare compare; 11 | public: 12 | sliding_window(Compare const & a_compare = Compare()) 13 | : compare(a_compare) {} 14 | T front() { // O(1), minimum 15 | return data.front().second; 16 | } 17 | void push_back(int i, T a) { // O(1) amortized. 18 | while (not data.empty() and compare(a, data.back().second)) { 19 | data.pop_back(); 20 | } 21 | data.emplace_back(i, a); 22 | } 23 | void pop_front(int i) { 24 | if (data.front().first == i) { 25 | data.pop_front(); 26 | } 27 | } 28 | void push_front(int i, T a) { 29 | if (data.empty() or not compare(data.front().second, a)) { 30 | data.emplace_front(i, a); 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /old/string-skip-list.inc.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector > get_next_index(Iterator first, Iterator last) { 3 | int n = distance(first, last); 4 | vector > x(n + 1); 5 | fill(whole(x[n]), n); 6 | repeat_reverse (i, n) { 7 | x[i] = x[i + 1]; 8 | x[i][*(first + i) - 'a'] = i; 9 | } 10 | return x; // x_{i, c} = \min \{ j \ge i \mid s_j = c \} 11 | } 12 | unittest { 13 | string s = "aabcab"; 14 | auto x = get_next_index(s.begin(), s.end()); 15 | assert (x[0][0] == 0); // () [a]abcab 16 | assert (x[0][1] == 2); // () aa[b]cab 17 | assert (x[0][2] == 3); // () aab[c]ab 18 | assert (x[4][0] == 4); // (aabc) [a]b 19 | assert (x[4][1] == 5); // (aabc) a[b] 20 | assert (x[4][2] == 6); // (aabc) ab[] 21 | } 22 | -------------------------------------------------------------------------------- /old/subset.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @sa https://kimiyuki.net/blog/2017/07/16/enumerate-sets-with-bit-manipulation/ 3 | */ 4 | 5 | // for a set z, list y \subseteq z, ascending order 6 | for (int y = 0; ; y = (y - z) & z) { 7 | ... 8 | if (y == z) break; 9 | } 10 | 11 | // for a set z, list y \subseteq z, descending order 12 | for (int y = z; ; y = (y - 1) & z) { 13 | ... 14 | if (y == 0) break; 15 | } 16 | 17 | // for a set x and an ordinal n, list y s.t. x \subseteq y \subseteq n 18 | or (int y = x; y < (1 << n); y = (y + 1) | x) { 19 | ... 20 | } 21 | 22 | // for an ordinal n and integer k, list x \subseteq n s.t. \|x\| = k 23 | for (int x = (1 << k) - 1; x < (1 << n); ) { 24 | ... 25 | int t = x | (x - 1); 26 | x = (t + 1) | (((~ t & - ~ t) - 1) >> (__builtin_ctz(x) + 1)); 27 | } 28 | -------------------------------------------------------------------------------- /old/suffix-array.inc.cpp: -------------------------------------------------------------------------------- 1 | int sa_lower_bound(string const & s, vector const & sa, string const & t) { // returns an index on suffix array 2 | int n = s.size(); 3 | int l = 0, r = n+1; // (l, r] 4 | while (l + 1 < r) { 5 | int m = (l + r) / 2; 6 | (s.compare(sa[m], string::npos, t) < 0 ? l : r) = m; 7 | } 8 | return r; 9 | } 10 | int sa_prefix_upper_bound(string const & s, vector const & sa, string const & t) { // returns an index on suffix array 11 | int n = s.size(); 12 | int l = 0, r = n+1; // (l, r] 13 | while (l + 1 < r) { 14 | int m = (l + r) / 2; 15 | (s.compare(sa[m], t.size(), t) <= 0 ? l : r) = m; 16 | } 17 | return r; 18 | } 19 | int sa_match(string const & target, string const & pattern, vector const & sa, segment_tree const & lcp) { // O(m \log n) 20 | int l = sa_lower_bound(target, sa, pattern); 21 | int r = sa_prefix_upper_bound(target, sa, pattern); 22 | return r - l; 23 | } 24 | -------------------------------------------------------------------------------- /old/ternary-search.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @arg f must be a downward-convex function 3 | * @retrun argmin f 4 | * @note f is called (iteration + 1) times 5 | */ 6 | template 7 | double golden_section_search(double l, double r, int iteration, Function f) { 8 | static const double GOLDEN_RATIO = (1 + sqrt(5)) / 2; 9 | double m1 = l + (r - l) / (GOLDEN_RATIO + 1); 10 | double m2 = l + (r - l) / GOLDEN_RATIO; // NOTE: this equals to GOLDEN_RATIO / (GOLDEN_RATIO + 1.0) 11 | double f1 = f(m1); 12 | double f2 = f(m2); 13 | while (iteration --) { 14 | if (f1 < f2){ 15 | r = m2; 16 | m2 = m1; 17 | f2 = f1; 18 | m1 = l + (r - l) / (GOLDEN_RATIO + 1); 19 | f1 = f(m1); 20 | } else { 21 | l = m1; 22 | m1 = m2; 23 | f1 = f2; 24 | m2 = l + (r - l) / GOLDEN_RATIO; 25 | f2 = f(m2); 26 | } 27 | } 28 | return (l + r) / 2; 29 | } 30 | -------------------------------------------------------------------------------- /old/trie-tree.inc.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct trie_t { 3 | T data; 4 | array, 26> children; 5 | }; 6 | template 7 | shared_ptr > trie_insert(shared_ptr > original_t, string const & s, T data) { 8 | if (not original_t) original_t = make_shared >(); 9 | auto t = original_t; 10 | for (char c : s) { 11 | assert (isalpha(c)); 12 | int i = toupper(c) - 'A'; 13 | if (not t->children[i]) t->children[i] = make_shared >(); 14 | t = t->children[i]; 15 | } 16 | t->data = data; 17 | return original_t; 18 | } 19 | template 20 | shared_ptr > trie_find(shared_ptr > const & t, string const & s, int i) { 21 | if (t == nullptr) return t; 22 | if (i == s.length()) return t; 23 | char c = s[i]; 24 | int j = toupper(c) - 'A'; 25 | return trie_find(t->children[j], s, i + 1); 26 | } 27 | -------------------------------------------------------------------------------- /old/two-edge-connected-components.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief 2-edge-connected components decomposition / 2-辺連結成分分解 3 | * @param g an adjacent list of the simple undirected graph 4 | * @note O(V + E) 5 | */ 6 | pair > decompose_to_two_edge_connected_components(vector > const & g) { 7 | int n = g.size(); 8 | vector imos(n); { // imos[i] == 0 iff the edge i -> parent is a bridge 9 | vector used(n); // 0: unused ; 1: exists on stack ; 2: removed from stack 10 | function go = [&](int i, int parent) { 11 | used[i] = 1; 12 | for (int j : g[i]) if (j != parent) { 13 | if (used[j] == 0) { 14 | go(j, i); 15 | imos[i] += imos[j]; 16 | } else if (used[j] == 1) { 17 | imos[i] += 1; 18 | imos[j] -= 1; 19 | } 20 | } 21 | used[i] = 2; 22 | }; 23 | REP (i, n) if (used[i] == 0) { 24 | go(i, -1); 25 | } 26 | } 27 | int size = 0; 28 | vector component_of(n, -1); { 29 | function go = [&](int i) { 30 | for (int j : g[i]) if (component_of[j] == -1) { 31 | component_of[j] = imos[j] == 0 ? size ++ : component_of[i]; 32 | go(j); 33 | } 34 | }; 35 | REP (i, n) if (component_of[i] == -1) { 36 | component_of[i] = size ++; 37 | go(i); 38 | } 39 | } 40 | return { size, move(component_of) }; 41 | } 42 | -------------------------------------------------------------------------------- /old/two-node-connected-components.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief 2-node-connected components decomposition / 2-頂点連結成分分解 3 | * @param g an adjacent list of the simple undirected graph 4 | * @note O(V + E) 5 | * @return list of (list of edges in the component) 6 | */ 7 | vector > > decompose_to_two_node_connected_components(vector > const & g) { 8 | int n = g.size(); 9 | vector ord(n, -1); 10 | vector low(n, -1); 11 | vector used(n); 12 | vector > > components; 13 | stack > stk; 14 | int k = 0; 15 | function go = [&](int i, int parent) { 16 | used[i] = true; 17 | ord[i] = k ++; 18 | low[i] = ord[i]; 19 | for (auto j : g[i]) if (j != parent) { 20 | if (ord[j] < ord[i]) { 21 | stk.emplace(minmax({ i, j })); 22 | } 23 | if (used[j]) { 24 | chmin(low[i], ord[j]); 25 | } else { 26 | go(j, i); 27 | chmin(low[i], low[j]); 28 | if (low[j] >= ord[i]) { 29 | components.emplace_back(); 30 | while (true) { 31 | pair e = stk.top(); 32 | components.back().push_back(e); 33 | stk.pop(); 34 | if (e == minmax({ i, j })) { 35 | break; 36 | } 37 | } 38 | } 39 | } 40 | } 41 | }; 42 | REP (i, n) if (not used[i]) { 43 | go(i, -1); 44 | } 45 | return components; 46 | } 47 | -------------------------------------------------------------------------------- /old/warshall-floyd.inc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Warshall-Floyd algorithm 3 | * @note O(n^3) 4 | * @param g is a digraph 5 | */ 6 | vector > warshall_floyd(vector > > const & g) { 7 | int n = g.size(); 8 | vector > dist(n, vector(n, LLONG_MAX)); 9 | REP (i, n) { 10 | dist[i][i] = 0; 11 | for (auto edge : g[i]) { 12 | int j; ll cost; tie(j, cost) = edge; 13 | dist[i][j] = cost; 14 | } 15 | } 16 | REP (k, n) { 17 | REP (i, n) if (dist[i][k] != LLONG_MAX) { 18 | REP (j, n) if (dist[k][j] != LLONG_MAX) { 19 | chmin(dist[i][j], dist[i][k] + dist[k][j]); 20 | } 21 | } 22 | } 23 | return dist; 24 | } 25 | 26 | /** 27 | * @brief Warshall-Floyd algorithm for connectivity 28 | */ 29 | vector > warshall_floyd(vector > const & g) { 30 | int n = g.size(); 31 | vector > conn(n, vector(n)); 32 | REP (i, n) { 33 | conn[i][i] = true; 34 | for (int j : g[i]) { 35 | conn[i][j] = true; 36 | } 37 | } 38 | REP (k, n) REP (i, n) REP (j, n) { 39 | if (conn[i][k] and conn[k][j]) { 40 | conn[i][j] = true; 41 | } 42 | } 43 | return conn; 44 | } 45 | -------------------------------------------------------------------------------- /old/xorshift.inc.cpp: -------------------------------------------------------------------------------- 1 | class xor_shift_128 { 2 | public: 3 | typedef uint32_t result_type; 4 | xor_shift_128(uint32_t seed = 42) { 5 | set_seed(seed); 6 | } 7 | void set_seed(uint32_t seed) { 8 | a = seed = 1812433253u * (seed ^ (seed >> 30)); 9 | b = seed = 1812433253u * (seed ^ (seed >> 30)) + 1; 10 | c = seed = 1812433253u * (seed ^ (seed >> 30)) + 2; 11 | d = seed = 1812433253u * (seed ^ (seed >> 30)) + 3; 12 | } 13 | uint32_t operator() () { 14 | uint32_t t = (a ^ (a << 11)); 15 | a = b; b = c; c = d; 16 | return d = (d ^ (d >> 19)) ^ (t ^ (t >> 8)); 17 | } 18 | static constexpr uint32_t max() { return numeric_limits::max(); } 19 | static constexpr uint32_t min() { return numeric_limits::min(); } 20 | private: 21 | uint32_t a, b, c, d; 22 | }; 23 | -------------------------------------------------------------------------------- /python/binary_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | def binsearch(l, r, pred): # [l, r) 3 | assert l < r 4 | l -= 1 5 | while r - l > 1: 6 | m = (l + r) // 2 7 | if pred(m): 8 | r = m 9 | else: 10 | l = m 11 | return r 12 | 13 | def binsearch_float(l, r, pred): # [l, r) 14 | assert l < r 15 | for _ in range(100): 16 | m = (l + r) / 2 17 | if pred(m): 18 | r = m 19 | else: 20 | l = m 21 | return r 22 | -------------------------------------------------------------------------------- /python/chinese_remainder_theorem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import gmpy2 3 | 4 | def chinese_remainder_theorem(eqn): 5 | ''' 6 | eqn = [ (y_0, n_0), ... ] where 7 | x = y_i mod n_i 8 | ''' 9 | x = 0 10 | m = 1 11 | for y, n in eqn: 12 | d = gmpy2.gcd(m, n) 13 | x += (m // d) * (y - x) * gmpy2.invert(m // d, n // d) 14 | m = gmpy2.lcm(m, n) 15 | return x % m 16 | 17 | def crt(eqn1, eqn2): 18 | x1, m1 = eqn1 19 | x2, m2 = eqn2 20 | d = int(gmpy2.gcd(m1, m2)) 21 | x = x1 + (m1 // d) * (x2 - x1) * int(gmpy2.invert(m1 // d, m2 // d)) 22 | m = int(gmpy2.lcm(m1, m2)) 23 | return x % m, m 24 | -------------------------------------------------------------------------------- /python/choose.py: -------------------------------------------------------------------------------- 1 | import array 2 | def get_fact(n, mod): 3 | fact = array.array('l') 4 | fact.append(1) 5 | for i in range(n): 6 | fact.append((i + 1) * fact[-1] % mod) 7 | return fact 8 | def choose(n, r, mod, fact=None): 9 | return fact[n] * pow(fact[n - r] * fact[r], mod - 2, mod) % mod 10 | -------------------------------------------------------------------------------- /python/extgcd.py: -------------------------------------------------------------------------------- 1 | def extgcd(a, b): 2 | if b == 0: 3 | return 1, 0 4 | else: 5 | na, nb = extgcd(b, a % b) 6 | return nb, na - a//b * nb 7 | def modinv(a, n): 8 | return extgcd(a, n)[0] % n 9 | -------------------------------------------------------------------------------- /python/matrix-modinv.py: -------------------------------------------------------------------------------- 1 | def modinv(a_f, m): 2 | f = np.copy(a_f) 3 | assert isinstance(f, np.ndarray) 4 | assert isinstance(m, int) 5 | n = a_f.shape[0] 6 | g = np.identity(n, dtype=int) 7 | for i in range(n): 8 | for j in range(i+1,n): 9 | try: 10 | gmpy2.invert(int(f[j,i]), m) 11 | f[i], f[j] = np.copy(f[j]), np.copy(f[i]) 12 | g[i], g[j] = np.copy(g[j]), np.copy(g[i]) 13 | break 14 | except: 15 | pass 16 | inv = int(gmpy2.invert(int(f[i,i]), m)) 17 | f[i] = f[i] * inv % m 18 | g[i] = g[i] * inv % m 19 | for j in range(n): 20 | if j != i: 21 | p = f[j,i] 22 | f[j] = (f[j] - f[i] * p) % m 23 | g[j] = (g[j] - g[i] * p) % m 24 | assert np.array_equal(f, np.identity(n, dtype=int)) 25 | assert np.array_equal(a_f.dot(g) % m, np.identity(n, dtype=int)) 26 | assert isinstance(g, np.ndarray) 27 | return g 28 | -------------------------------------------------------------------------------- /python/miller_rabin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def is_prime(n, k=20): # miller-rabin primality test 4 | if n == 2: 5 | return True 6 | if n == 1 or n % 2 == 0: 7 | return False 8 | d = n - 1 9 | while d % 2 == 0: 10 | d //= 2 11 | for _ in range(k): 12 | a = random.randint(1,n-2) 13 | t = d 14 | y = pow(a,t,n) 15 | while t != n-1 and y != 1 and y != n-1: 16 | y = (y * y) % n 17 | t <<= 1 18 | if y != n-1 and t & 1 == 0: 19 | return False 20 | return True 21 | -------------------------------------------------------------------------------- /python/rational-gcd.py: -------------------------------------------------------------------------------- 1 | from fractions import Fraction 2 | import math 3 | def lcm(a, b): 4 | return a * b // math.gcd(a, b) 5 | 6 | # https://kimiyuki.net/blog/2016/06/08/yuki-356/ 7 | def qlcm(p, q): 8 | a = p.numerator * q.denominator 9 | b = p.denominator * q.numerator 10 | c = p.denominator * q.denominator 11 | return Fraction(lcm(a, b), c) 12 | def qgcd(p, q): 13 | return p * q / qlcm(p, q) 14 | -------------------------------------------------------------------------------- /string/longest_common_prefix.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../string/suffix_array.hpp" 6 | #include "../data_structure/sparse_table.hpp" 7 | #include "../monoids/min.hpp" 8 | 9 | /** 10 | * @brief Longest Common Prefix / 最長共通接頭辞 (接尾辞配列, 前処理 $O(N (\log N)^2)$ + $O(1)$) 11 | */ 12 | class longest_common_prefix { 13 | std::vector rank; 14 | sparse_table > table; 15 | 16 | void initialize(const std::string & s, const std::vector & sa) { 17 | int n = s.length(); 18 | std::vector lcp(n, -1); // lcp[i] is the length of the common prefix between i-th and (i+1)-th substring of s 19 | int h = 0; 20 | lcp[0] = 0; 21 | REP (i, n) { 22 | int j = sa[rank[i] - 1]; 23 | if (h > 0) -- h; 24 | while (j + h < n and i + h < n and s[j + h] == s[i + h]) ++ h; 25 | lcp[rank[i] - 1] = h; 26 | } 27 | table = sparse_table >(ALL(lcp)); 28 | } 29 | 30 | public: 31 | longest_common_prefix(const std::string & s) { 32 | std::vector sa; 33 | compute_suffix_array(s, sa, rank); 34 | initialize(s, sa); 35 | } 36 | longest_common_prefix(const std::string & s, const std::vector & sa, const std::vector & rank_) 37 | : rank(rank_) { 38 | initialize(s, sa); 39 | } 40 | 41 | int get(int i, int j) const { 42 | int l = rank[i]; 43 | int r = rank[j]; 44 | if (l > r) std::swap(l, r); 45 | int n = rank.size() - 1; 46 | return std::min(n, table.range_get(l, r)); 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /string/longest_common_prefix.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/zalgorithm" 2 | #include "../string/longest_common_prefix.hpp" 3 | #include "../hack/fastio.hpp" 4 | 5 | int main() { 6 | std::string s = in(); 7 | int n = s.length(); 8 | longest_common_prefix lcp(s); 9 | REP (i, n) { 10 | out(lcp.get(0, i)); 11 | out(i < n - 1 ? ' ' : '\n'); 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /string/suffix_array.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../utils/macros.hpp" 7 | 8 | /** 9 | * @brief Suffix Array / 接尾辞配列 ($O(N (\log N)^2)$, Manber & Myers) 10 | * @arg sa[i] is the index of i-th smallest substring of s, s[sa[i], N) 11 | * @arg rank[i] is the rank of substring s[i, N) 12 | * @note 蟻本より 13 | */ 14 | void compute_suffix_array(std::string const & s, std::vector & sa, std::vector & rank) { 15 | int n = s.length(); 16 | sa.resize(n + 1); 17 | rank.resize(n + 1); 18 | REP (i, n + 1) { 19 | sa[i] = i; 20 | rank[i] = i < n ? s[i] : -1; 21 | } 22 | auto rankf = [&](int i) { 23 | return i <= n ? rank[i] : -1; 24 | }; 25 | std::vector nxt(n + 1); 26 | for (int k = 1; k <= n; k <<= 1) { 27 | auto cmp = [&](int i, int j) { 28 | return std::make_pair(rank[i], rankf(i + k)) < std::make_pair(rank[j], rankf(j + k)); 29 | }; 30 | std::sort(sa.begin(), sa.end(), cmp); 31 | nxt[sa[0]] = 0; 32 | REP3 (i, 1, n + 1) { 33 | nxt[sa[i]] = nxt[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0); 34 | } 35 | rank.swap(nxt); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /string/suffix_array.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/suffixarray" 2 | #include 3 | #include 4 | #include 5 | #include "../string/suffix_array.hpp" 6 | #include "../hack/fastio.hpp" 7 | using namespace std; 8 | 9 | int main() { 10 | // input 11 | string s = in(); 12 | int n = s.length(); 13 | 14 | // solve 15 | vector sa, rank; 16 | compute_suffix_array(s, sa, rank); 17 | assert ((int)sa.size() == n + 1); 18 | assert (sa[0] == n); 19 | 20 | // output 21 | REP (i, n) { 22 | out(sa[i + 1]); 23 | out(i < n - 1 ? ' ' : '\n'); 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i)) 3 | #define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i)) 4 | #define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i)) 5 | #define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i)) 6 | #define ALL(x) std::begin(x), std::end(x) 7 | #define dump(x) cerr << #x " = " << x << endl 8 | using namespace std; 9 | template using reversed_priority_queue = priority_queue, greater >; 10 | template inline void chmax(T & a, U const & b) { a = max(a, b); } 11 | template inline void chmin(T & a, U const & b) { a = min(a, b); } 12 | template auto make_table(X x, T a) { return vector(x, a); } 13 | template auto make_table(X x, Y y, Z z, Zs... zs) { auto cont = make_table(y, z, zs...); return vector(x, cont); } 14 | template ostream & operator << (ostream & out, vector const & xs) { REP (i, (int)xs.size() - 1) out << xs[i] << ' '; if (not xs.empty()) out << xs.back(); return out; } 15 | template struct fix_type { Functor functor; template decltype(auto) operator() (Args && ... args) const & { return functor(functor, std::forward(args)...); } }; 16 | template fix_type::type> fix(Functor && functor) { return { std::forward(functor) }; } 17 | 18 | int main() { 19 | ios::sync_with_stdio(false); 20 | cin.tie(nullptr); 21 | constexpr char endl = '\n'; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /utils/binary_search.aoj.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_4_B" 2 | #include "../utils/binary_search.hpp" 3 | #include "../utils/binary_search_max.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../utils/macros.hpp" 10 | using namespace std; 11 | 12 | int main() { 13 | int n; cin >> n; 14 | vector s(n); 15 | REP (i, n) { 16 | cin >> s[i]; 17 | } 18 | 19 | int q; cin >> q; 20 | int64_t cnt = 0; 21 | while (q --) { 22 | int t_i; cin >> t_i; 23 | int l = binsearch(0, n, [&](int i) { 24 | return s[i] >= t_i; 25 | }); 26 | cnt += (l < n and s[l] == t_i); 27 | 28 | int r = binsearch_max(0, n, [&](int i) { 29 | return s[i] <= t_i; 30 | }); 31 | assert ((l < n and s[l] == t_i) == (l <= r)); 32 | } 33 | 34 | cout << cnt << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /utils/binary_search.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | /** 6 | * @brief a binary search / 二分探索 7 | * @param[in] p a monotone predicate defined on $[l, r)$ 8 | * @return $\min \lbrace x \in [l, r) \mid p(x) \rbrace$, or r if it doesn't exist 9 | */ 10 | template 11 | int64_t binsearch(int64_t l, int64_t r, UnaryPredicate p) { 12 | assert (l <= r); 13 | -- l; 14 | while (r - l > 1) { 15 | int64_t m = l + (r - l) / 2; 16 | (p(m) ? r : l) = m; 17 | } 18 | return r; 19 | } 20 | -------------------------------------------------------------------------------- /utils/binary_search_float.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../utils/macros.hpp" 4 | 5 | /** 6 | * @brief a binary search on floating point numbers / 二分探索 (浮動小数点数) 7 | */ 8 | template 9 | double binsearch_float(double l, double r, UnaryPredicate p) { 10 | assert (l <= r); 11 | REP (i, Iteration) { 12 | double m = (l + r) / 2; 13 | (p(m) ? r : l) = m; 14 | } 15 | return r; 16 | } 17 | -------------------------------------------------------------------------------- /utils/binary_search_max.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | /** 6 | * @return $\max \lbrace x \in (l, r] \mid p(x) \rbrace$, or l if it doesn't exist 7 | */ 8 | template 9 | int64_t binsearch_max(int64_t l, int64_t r, UnaryPredicate p) { 10 | assert (l <= r); 11 | ++ r; 12 | while (r - l > 1) { 13 | int64_t m = l + (r - l) / 2; 14 | (p(m) ? l : r) = m; 15 | } 16 | return l; 17 | } 18 | -------------------------------------------------------------------------------- /utils/coordinate_compression.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../utils/macros.hpp" 5 | 6 | template 7 | struct coordinate_compression { 8 | std::vector data; 9 | coordinate_compression() = default; 10 | template 11 | coordinate_compression(Iterator first, Iterator last) { 12 | unsafe_insert(first, last); 13 | unsafe_rebuild(); 14 | } 15 | template 16 | void unsafe_insert(Iterator first, Iterator last) { 17 | data.insert(data.end(), first, last); 18 | } 19 | void unsafe_rebuild() { 20 | std::sort(ALL(data)); 21 | data.erase(std::unique(ALL(data)), data.end()); 22 | } 23 | int operator [] (const T & value) { 24 | return std::lower_bound(ALL(data), value) - data.begin(); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /utils/fast_zeta_transform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../number/primes.hpp" 5 | #include "../utils/macros.hpp" 6 | 7 | /** 8 | * @brief upward fast zeta transform on primes 9 | * @note $O(n \log n)$ (or, $O(n \log \log n)$ ???) 10 | * @return $b_i = \sum _ {i \mid j} a_j$ 11 | * @note $a_0, b_0$ means the greatest element 12 | */ 13 | template 14 | std::vector upward_fast_zeta_transform_on_primes(std::vector a, const prepared_primes & primes, const CommutativeSemiring & mon = CommutativeSemiring()) { 15 | assert (a.size() <= primes.size); 16 | if (a.empty()) return a; 17 | for (int64_t p : primes.primes) { 18 | REP3R (x, 1, (a.size() - 1) / p + 1) { 19 | a[x] = mon.mult(a[x], a[p * x]); 20 | } 21 | } 22 | REP3 (x, 1, a.size()) { 23 | a[x] = mon.mult(a[x], a[0]); 24 | } 25 | return a; 26 | } 27 | -------------------------------------------------------------------------------- /utils/macros.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i)) 3 | #define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i)) 4 | #define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i)) 5 | #define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i)) 6 | #define ALL(x) std::begin(x), std::end(x) 7 | -------------------------------------------------------------------------------- /utils/mex.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * @brief Minimum Excluded Value ($O(n)$ for a given sorted container) 6 | * @sa https://en.wikipedia.org/wiki/Mex_(mathematics) 7 | * @note xs must be weakly increasing 8 | */ 9 | template 10 | int mex(InputIterator first, InputIterator last) { 11 | int last_x = 0; // only for debug 12 | int y = 0; 13 | for (; first != last; ++ first) { 14 | int x = *first; 15 | assert (last_x <= x); 16 | last_x = x; 17 | if (y < x) break; 18 | if (y == x) ++ y; 19 | } 20 | return y; 21 | } 22 | -------------------------------------------------------------------------------- /utils/mex_calculator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class mex_calculator { 5 | uint64_t used; 6 | public: 7 | mex_calculator() 8 | : used(0) { 9 | } 10 | void put(int x) { 11 | assert (0 <= x and x < 64 - 1); 12 | used |= 1ull << x; 13 | } 14 | int get() const { 15 | return __builtin_ctzll(~ used); 16 | } 17 | void clear() { 18 | used = 0; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /utils/mo_algorithm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // struct mo_struct { 10 | // typedef int64_t value_type; 11 | // typedef int64_t result_type; 12 | // void add_right(int nr, value_type x_r) { 13 | // } 14 | // void add_left(int nl, value_type x_nl) { 15 | // } 16 | // void remove_right(int nr, value_type x_nr) { 17 | // } 18 | // void remove_left(int nl, value_type x_l) { 19 | // } 20 | // result_type query() { 21 | // return 0; 22 | // } 23 | // }; 24 | 25 | template 26 | std::vector run_mo_algorithm(Mo mo, const std::vector& values, const std::vector >& queries) { 27 | int n = values.size(); 28 | int m = queries.size(); 29 | 30 | // sort queries 31 | int sq_n = std::sqrt(n); 32 | std::vector order(m); 33 | std::iota(ALL(order), 0); 34 | std::sort(ALL(order), [&](int i, int j) { 35 | int l_i, r_i; std::tie(l_i, r_i) = queries[i]; 36 | int l_j, r_j; std::tie(l_j, r_j) = queries[j]; 37 | return std::make_pair(l_i / sq_n, r_i) < std::make_pair(l_j / sq_n, r_j); 38 | }); 39 | 40 | // compute queries 41 | std::vector ans(m); 42 | int l = 0; 43 | int r = 0; 44 | for (int j : order) { 45 | int nl, nr; std::tie(nl, nr) = queries[j]; 46 | for (; r < nr; ++ r) mo.add_right(r + 1, values[r]); 47 | for (; nl < l; -- l) mo.add_left(l - 1, values[l - 1]); 48 | for (; nr < r; -- r) mo.remove_right(r - 1, values[r - 1]); 49 | for (; l < nl; ++ l) mo.remove_left(l + 1, values[l]); 50 | ans[j] = mo.query(); 51 | } 52 | return ans; 53 | } 54 | -------------------------------------------------------------------------------- /utils/next_combination.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * @note copied from the reference implementation of N2639 6 | * @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2639.pdf 7 | */ 8 | template 9 | bool next_combination(BidirectionalIterator first1, BidirectionalIterator last1, BidirectionalIterator first2, BidirectionalIterator last2) { 10 | if (first1 == last1 or first2 == last2) { 11 | return false; 12 | } 13 | BidirectionalIterator m1 = last1; 14 | BidirectionalIterator m2 = last2; 15 | -- m2; 16 | while (-- m1 != first1 and not (*m1 < *m2)) { 17 | } 18 | bool result = (m1 == first1) and not (*first1 < *m2); 19 | if (! result ) { 20 | while (first2 != m2 and not (*m1 < *first2)) { 21 | ++ first2; 22 | } 23 | first1 = m1; 24 | std::iter_swap(first1, first2); 25 | ++ first1; 26 | ++ first2; 27 | } 28 | if (first1 != last1 and first2 != last2) { 29 | m1 = last1; 30 | m2 = first2; 31 | while (m1 != first1 and m2 != last2) { 32 | std::iter_swap(-- m1, m2); 33 | ++ m2; 34 | } 35 | std::reverse(first1, m1); 36 | std::reverse(first1, last1); 37 | std::reverse(m2, last2); 38 | std::reverse(first2, last2); 39 | } 40 | return not result; 41 | } 42 | 43 | template 44 | bool next_combination(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last) { 45 | return next_combination(first, middle, middle, last); 46 | } 47 | 48 | template 49 | inline bool prev_combination(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last) { 50 | return next_combination(middle, last, first, middle); 51 | } 52 | -------------------------------------------------------------------------------- /utils/two_satisfiability.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "../graph/strongly_connected_components.hpp" 6 | 7 | /** 8 | * @brief 2-SAT ($O(N)$) 9 | * @param n is the number of variables 10 | * @param cnf is a proposition in a conjunctive normal form. Each literal is expressed as number $x$ s.t. $1 \le \vert x \vert \le n$ 11 | * @return a vector with the length $n$ if SAT. It's empty if UNSAT. 12 | */ 13 | std::vector compute_two_satisfiability(int n, const std::vector > & cnf) { 14 | // make digraph 15 | std::vector > g(2 * n); 16 | auto index = [&](int x) { 17 | assert (x != 0 and abs(x) <= n); 18 | return x > 0 ? x - 1 : n - x - 1; 19 | }; 20 | for (auto it : cnf) { 21 | int x, y; std::tie(x, y) = it; // x or y 22 | g[index(- x)].push_back(index(y)); // not x implies y 23 | g[index(- y)].push_back(index(x)); // not y implies x 24 | } 25 | 26 | // do SCC 27 | std::vector component = decompose_to_strongly_connected_components(g).second; 28 | std::vector valuation(n); 29 | REP3 (x, 1, n + 1) { 30 | if (component[index(x)] == component[index(- x)]) { // x iff not x 31 | return std::vector(); // unsat 32 | } 33 | valuation[x - 1] = component[index(x)] > component[index(- x)]; // use components which indices are large 34 | } 35 | return valuation; 36 | } 37 | -------------------------------------------------------------------------------- /utils/two_satisfiability.yosupo.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/two_sat" 2 | #include 3 | #include 4 | #include 5 | #include "../utils/macros.hpp" 6 | #include "../hack/fastio.hpp" 7 | #include "../utils/two_satisfiability.hpp" 8 | using namespace std; 9 | 10 | int main() { 11 | // read the header of DIMACS format 12 | char const_p = in(); 13 | assert (const_p == 'p'); 14 | string const_cnf = in(); 15 | assert (const_cnf == "cnf"); 16 | 17 | // input 18 | int n = in(); 19 | int m = in(); 20 | vector > cnf; 21 | REP (i, m) { 22 | int a = in(); 23 | int b = in(); 24 | cnf.emplace_back(a, b); 25 | 26 | int const_zero = in(); 27 | assert (const_zero == 0); 28 | } 29 | 30 | // solve 31 | vector model = compute_two_satisfiability(n, cnf); 32 | 33 | // output 34 | if (model.empty()) { 35 | out("s UNSATISFIABLE\n"); 36 | } else { 37 | out("s SATISFIABLE\n"); 38 | out('v'); 39 | REP (i, n) { 40 | out(' '); 41 | out((model[i] ? 1 : -1) * (i + 1)); 42 | } 43 | out(" 0 \n"); 44 | } 45 | return 0; 46 | } 47 | --------------------------------------------------------------------------------