1/*2 * Copyright (c) 2026 Bruno Monteiro3 *4 * Permission is hereby granted, free of charge, to any person obtaining a copy5 * of this software and associated documentation files (the "Software"), to deal6 * in the Software without restriction, including without limitation the rights7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell8 * copies of the Software, and to permit persons to whom the Software is9 * furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN20 * THE SOFTWARE.21 */2223#pragma once2425#include <algorithm>26#include <bitset>27#include <cstdint>28#include <functional>29#include <initializer_list>30#include <iomanip>31#include <iostream>32#include <limits>33#include <map>34#include <optional>35#include <queue>36#include <random>37#include <set>38#include <sstream>39#include <stdexcept>40#include <string>41#include <sys/types.h>42#include <type_traits>43#include <unordered_map>44#include <unordered_set>45#include <utility>46#include <vector>4748namespace tgen {4950/**************************51 * *52 * GENERAL OPERATIONS *53 * *54 **************************/5556namespace detail {5758// Type aliases.59using u128 = unsigned __int128;60using i128 = __int128;6162/*63 * Error handling.64 */6566inline void throw_assertion_error(const std::string &condition,67 const std::string &msg, const char *file,68 int line) {69 throw std::runtime_error("tgen: " + msg + " (assertion `" + condition +70 "` failed at " + file + ":" +71 std::to_string(line) + ")");72}73inline void throw_assertion_error(const std::string &condition,74 const char *file, int line) {75 throw std::runtime_error("tgen: assertion `" + condition + "` failed at " +76 std::string(file) + ":" + std::to_string(line));77}78inline std::runtime_error error(const std::string &msg) {79 return std::runtime_error("tgen: " + msg);80}81inline std::runtime_error contradiction_error(const std::string &type,82 const std::string &msg = "") {83 // Tried to generate a contradictory type.84 std::string error_msg =85 type + ": invalid " + type + " (contradictory restrictions)";86 if (!msg.empty())87 error_msg += ": " + msg;88 return error(error_msg);89}90inline std::runtime_error91complex_restrictions_error(const std::string &type,92 const std::string &msg = "") {93 // Tried to generate a type with too many distinct restrictions.94 std::string error_msg =95 type + ": cannot represent " + type + " (complex restrictions)";96 if (!msg.empty())97 error_msg += ": " + msg;98 return error(error_msg);99}100inline void tgen_ensure_against_bug(bool cond, const std::string &msg = "") {101 if (!cond) {102 std::string error_msg;103 if (!msg.empty())104 error_msg = "tgen: " + msg + "\n";105 error_msg += "tgen: THERE IS A BUG IN TGEN; PLEASE CONTACT MAINTAINERS";106 throw std::runtime_error(error_msg);107 }108}109110// Ensures condition is true, with a clear error message on failure.111#define tgen_ensure(cond, ...) \112 if (!(cond)) \113 tgen::detail::throw_assertion_error(#cond, ##__VA_ARGS__, __FILE__, \114 __LINE__)115116// Registering checks.117inline bool registered = false;118inline void ensure_registered() {119 tgen_ensure(registered,120 "tgen was not registered! You should call "121 "tgen::register_gen(argc, argv) before running tgen functions");122}123124// Template magic to detect types at compile time.125126// Detects containers != std::string.127template <typename T, typename = void> struct is_container : std::false_type {};128template <typename T>129struct is_container<T,130 std::void_t<typename std::remove_reference_t<T>::value_type,131 decltype(std::begin(std::declval<T>())),132 decltype(std::end(std::declval<T>()))>>133 : std::true_type {};134// Exclude all basic_string variants135template <typename Char, typename Traits, typename Alloc>136struct is_container<std::basic_string<Char, Traits, Alloc>> : std::false_type {137};138template <typename Char, typename Traits, typename Alloc>139struct is_container<const std::basic_string<Char, Traits, Alloc>>140 : std::false_type {};141template <typename Char, typename Traits, typename Alloc>142struct is_container<std::basic_string<Char, Traits, Alloc> &>143 : std::false_type {};144template <typename Char, typename Traits, typename Alloc>145struct is_container<const std::basic_string<Char, Traits, Alloc> &>146 : std::false_type {};147148// Detects std::pair.149template <typename T> struct is_pair : std::false_type {};150template <typename A, typename B>151struct is_pair<std::pair<A, B>> : std::true_type {};152// Detects std::tuple.153template <typename T> struct is_tuple : std::false_type {};154template <typename... Ts>155struct is_tuple<std::tuple<Ts...>> : std::true_type {};156// Detects scalar (printed atomically).157template <typename T>158struct is_scalar159 : std::bool_constant<!is_container<T>::value and !is_tuple<T>::value and160 !is_pair<T>::value> {};161// Detects complex container.162template <typename T>163struct is_container_multiline164 : std::bool_constant<is_container<T>::value and165 !is_scalar<typename std::remove_cv_t<166 std::remove_reference_t<T>>::value_type>::value> {167};168// Detects complex std::pair.169template <typename T> struct is_pair_multiline : std::false_type {};170template <typename A, typename B>171struct is_pair_multiline<std::pair<A, B>>172 : std::bool_constant<!is_scalar<A>::value or !is_scalar<B>::value> {};173// Detects complex std::tuple.174template <typename Tuple> struct is_tuple_multiline : std::false_type {};175template <typename... Ts>176struct is_tuple_multiline<std::tuple<Ts...>>177 : std::bool_constant<(!is_scalar<Ts>::value or ...)> {};178179// Used to return false at compile time only if evaluated.180template <typename> inline constexpr bool dependent_false_v = false;181182/*183 * Properties of custom types.184 */185186// If type is sequential (list-like).187using is_sequential_tag = void;188189// Detects associative containers.190template <typename T, typename = void>191struct is_associative_container : std::false_type {};192template <typename T>193struct is_associative_container<194 T, std::void_t<typename T::key_type, typename T::key_compare>>195 : std::true_type {};196197// Detects sequential generator values.198template <typename T, typename = void>199struct is_sequential : std::false_type {};200template <typename T>201struct is_sequential<202 T, std::void_t<typename std::decay_t<T>::tgen_is_sequential_tag>>203 : std::true_type {};204205/*206 * Unique rng to use.207 */208209// The single rng to be used by the library.210inline std::mt19937 rng;211212/*213 * Printing.214 */215216// Print view struct for printing either a container or a sequential generator217// element.218template <typename T,219 bool IsCont = detail::is_container<std::decay_t<T>>::value>220struct print_cols_view;221222// Container.223template <typename T> struct print_cols_view<T, true> {224 const T &value;225 decltype(std::begin(std::declval<const T &>())) it;226227 print_cols_view(const T &v) : value(v), it(v.begin()) {}228229 std::size_t size() const { return value.size(); }230 decltype(auto) get(std::size_t) const { return *it; }231 void advance() { ++it; }232};233234// Sequential generator element.235template <typename T> struct print_cols_view<T, false> {236 const T &value;237238 print_cols_view(const T &v) : value(v) {}239240 std::size_t size() const { return value.size(); }241 decltype(auto) get(std::size_t i) const { return value[i]; }242 void advance() {}243};244245/*246 * Distinct generation.247 */248249// Rejection cap is multiplier * |seen|; with one value left, falsely reporting250// exhaustion has probability about e^{-84} < 10^{-36}.251constexpr int distinct_attempt_multiplier = 84;252253// One rejection-sampling step for distinct generation.254// O(T * log k + log^2 k) amortized expected time per call when generating k255// distinct values and next() runs in O(T).256template <typename Seen, typename Fn>257auto try_generate_distinct(Seen &seen, Fn &&next, bool insert = true)258 -> std::optional<std::invoke_result_t<Fn &>> {259 using T = std::invoke_result_t<Fn &>;260 size_t attempts =261 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());262 for (size_t i = 0; i < attempts; ++i) {263 T val = next();264 if (insert) {265 if (seen.insert(val).second)266 return val;267 } else if (seen.count(val) == 0)268 return val;269 }270 return std::nullopt;271}272273} // namespace detail274275/*276 * Compiler configuration (see set_compiler).277 */278279// Kinds of compilers.280enum class compiler_kind { gcc, clang, unknown };281282// Compiler identity and version.283struct compiler_value {284 compiler_kind kind_;285 int major_;286 int minor_;287288 compiler_value(compiler_kind kind = compiler_kind::unknown, int major = 0,289 int minor = 0)290 : kind_(kind), major_(major), minor_(minor) {}291};292293namespace detail {294295// Global C++ version value (0 means unknown).296struct cpp_value {297 int version_;298299 cpp_value(std::optional<int> version = std::nullopt)300 : version_(version ? *version : 0) {301 if (version) {302 tgen_ensure(*version == 17 or *version == 20 or *version == 23,303 "unsupported C++ version (use 17, 20, 23)");304 }305 }306};307308inline cpp_value cpp;309inline compiler_value compiler;310311} // namespace detail312313/*314 * Base classes.315 */316317// Needed for return type of some functions.318template <typename T> struct list;319320// Generates distinct values of a function.321template <typename Func, typename... Args> struct distinct {322 Func func_;323 std::tuple<Args...> args_;324 using T = std::invoke_result_t<Func &, Args &...>;325 std::set<T> seen_;326327 distinct(Func func, Args... args)328 : func_(std::move(func)), args_(std::move(args)...) {}329330 // Generates a distinct value (i.e., one not returned before).331 //332 // Assume gen() produces a uniformly random value in O(T) time.333 // Since duplicates are rejected, the expected number of trials over334 // k successful generations is:335 //336 // sum_{i=1}^k k / i = O(k log k)337 //338 // (coupon collector argument).339 //340 // Each trial additionally performs O(log k) work to check/store341 // previously generated values, yielding a total time of342 // O((T + log k) * k log k).343 //344 // Thus, the amortized expected time per call is345 // O(T * log k + log^2 k).346 //347 // With extremely small probability (< 1e-18), the algorithm may348 // incorrectly report that no more distinct values exist.349 auto gen() {350 auto val = generate_distinct(true);351 if (val)352 return *val;353354 throw detail::error("distinct: no more distinct values");355 }356 template <typename U> auto gen(std::initializer_list<U> il) {357 return gen(std::vector<U>(il));358 }359360 // Generates a list of distinct values.361 auto gen_list(int size) {362 std::vector<T> res;363 for (int i = 0; i < size; ++i)364 res.push_back(gen());365366 return typename list<T>::value(res);367 }368369 // Checks if there are no more distinct values.370 // With extremely small probability (< 1e-18), the algorithm may371 // incorrectly report that there are no more distinct values.372 bool empty() { return generate_distinct(false) == std::nullopt; }373374 // Generates all distinct values.375 auto gen_all() {376 std::vector<T> res;377 while (true) {378 auto val = generate_distinct(true);379 if (val)380 res.push_back(*val);381 else382 break;383 }384 return typename list<T>::value(res);385 }386387 // Nice error for `out << distinct`.388 friend std::ostream &operator<<(std::ostream &out, const distinct &) {389 static_assert(390 detail::dependent_false_v<distinct>,391 "distinct: cannot print a distinct generator. Maybe you forgot to "392 "call `gen()`?");393 return out;394 }395396 private:397 // Generates distinct value and inserts it if `insert` is true.398 // Returns the value if found, otherwise returns std::nullopt.399 auto generate_distinct(bool insert) {400 return detail::try_generate_distinct(401 seen_, [&] { return std::apply(func_, args_); }, insert);402 }403};404template <typename Func, typename... Args>405distinct(Func, Args...) -> distinct<Func, Args...>;406407// Base struct for generators.408template <typename Gen> struct gen_base {409 const Gen &self() const { return *static_cast<const Gen *>(this); }410411 template <typename... Args> auto gen_list(int size, Args &&...args) const {412 std::vector<typename Gen::value> res;413414 for (int i = 0; i < size; ++i)415 res.push_back(static_cast<const Gen *>(this)->gen(416 std::forward<Args>(args)...));417418 return typename list<typename Gen::value>::value(res);419 }420421 // Calls the generator until predicate is true.422 template <typename Pred, typename... Args>423 auto gen_until(Pred predicate, int max_tries, Args &&...args) const {424 for (int i = 0; i < max_tries; ++i) {425 typename Gen::value val = static_cast<const Gen *>(this)->gen(426 std::forward<Args>(args)...);427428 if (predicate(val))429 return val;430 }431432 throw detail::error("could not generate value matching predicate");433 }434 template <typename Pred, typename T, typename... Args>435 auto gen_until(Pred predicate, int max_tries, std::initializer_list<T> il,436 Args &&...args) const {437 return gen_until(predicate, max_tries, std::vector<T>(il),438 std::forward<Args>(args)...);439 }440441 // Distinct for generator.442 template <typename... Args> auto distinct(Args &&...args) const {443 return tgen::distinct(444 [self = self()](auto &&...inner_args) mutable -> decltype(auto) {445 return self.gen(446 std::forward<decltype(inner_args)>(inner_args)...);447 },448 std::forward<Args>(args)...);449 }450 template <typename T, typename... Args>451 auto distinct(std::initializer_list<T> il, Args &&...args) const {452 return distinct(std::vector<T>(il), std::forward<Args>(args)...);453 }454455 // Nice error for `out << generator`.456 friend std::ostream &operator<<(std::ostream &out, const gen_base &) {457 static_assert(detail::dependent_false_v<gen_base>,458 "gen_base: cannot print a generator. Maybe you forgot to "459 "call `gen()`?");460 return out;461 }462};463464// Base class for generator values.465template <typename Val> struct gen_value_base {466 const Val &self() const { return *static_cast<const Val *>(this); }467468 bool operator<(const Val &rhs) const {469 return self().to_std() < rhs.to_std();470 }471};472473namespace detail {474475// Detects generator values.476template <typename T>477struct is_generator_value478 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};479480} // namespace detail481482/*483 * Easier printing.484 */485486// Struct to print standard types to std::ostream;487struct print {488 std::string s_;489490 template <typename T> print(const T &val, char sep = ' ') {491 std::ostringstream oss;492 write(oss, val, sep);493 s_ = oss.str();494 }495 template <typename T>496 print(const std::initializer_list<T> &il, char sep = ' ') {497 std::ostringstream oss;498 write(oss, std::vector<T>(il), sep);499 s_ = oss.str();500 }501 template <typename T>502 print(const std::initializer_list<std::initializer_list<T>> &il,503 char sep = ' ') {504 std::ostringstream oss;505 std::vector<std::vector<T>> mat;506 for (const auto &i : il)507 mat.push_back(i);508 write(oss, mat, sep);509 s_ = oss.str();510 }511512 template <typename T> void write(std::ostream &os, const T &val, char sep) {513 if constexpr (detail::is_pair<T>::value) {514 if constexpr (detail::is_pair_multiline<T>::value) {515 write(os, val.first, sep);516 os << '\n';517 write(os, val.second, sep);518 } else {519 // Use space for inner separator.520 write(os, val.first, ' ');521 os << sep;522 write(os, val.second, ' ');523 }524 } else if constexpr (detail::is_tuple<T>::value)525 write_tuple(os, val, sep);526 else if constexpr (detail::is_container<T>::value)527 write_container(os, val, sep);528 else if constexpr (std::is_same_v<T, detail::i128> or529 std::is_same_v<T, detail::u128>)530 write_128_number(os, val);531 else532 os << val;533 }534535 // Writes 128 bit number.536 template <typename T> void write_128_number(std::ostream &os, T num) {537 static const long long BASE = 1e18;538539 if (num < 0) {540 os << '-';541 num = -num;542 }543544 if (num >= BASE) {545 write_128_number(os, num / BASE);546 os << std::setw(18) << std::setfill('0')547 << static_cast<long long>(num % BASE);548 } else549 os << static_cast<long long>(num);550 }551 // Writes container, checking separator.552 template <typename C>553 void write_container(std::ostream &os, const C &container, char sep) {554 bool first = true;555556 for (const auto &e : container) {557 if (!first)558 os << (detail::is_container_multiline<C>::value ? '\n' : sep);559 first = false;560 write(os, e, detail::is_container_multiline<C>::value ? sep : ' ');561 }562 }563564 // Writes tuple, checking separator.565 template <typename Tuple, size_t... I>566 void write_tuple_impl(std::ostream &os, const Tuple &tp, char sep,567 std::index_sequence<I...>) {568 bool first = true;569 ((os << (first ? (first = false, "")570 : (detail::is_tuple_multiline<Tuple>::value571 ? "\n"572 : std::string(1, sep))),573 write(os, std::get<I>(tp),574 detail::is_tuple_multiline<Tuple>::value ? sep : ' ')),575 ...);576 }577 template <typename T>578 void write_tuple(std::ostream &os, const T &tp, char sep) {579 write_tuple_impl(os, tp, sep,580 std::make_index_sequence<std::tuple_size<T>::value>{});581 }582583 friend std::ostream &operator<<(std::ostream &out, const print &pr) {584 return out << pr.s_;585 }586};587588// Prints in a new line.589struct println : print {590 template <typename T>591 println(const T &val, char sep = ' ') : print(val, sep) {}592 template <typename T>593 println(const std::initializer_list<T> &il, char sep = ' ')594 : print(il, sep) {}595 template <typename T>596 println(const std::initializer_list<std::initializer_list<T>> &il,597 char sep = ' ')598 : print(il, sep) {}599600 friend std::ostream &operator<<(std::ostream &out, const println &pr) {601 return out << pr.s_ << '\n';602 }603};604605// Prints container / sequential generator value on its own column.606// Example:607// A = {1, 2, 3}, B = {4, 2, 5}608// print_each(A, B) will print:609// "1 4610// 2 2611// 3 5612//",613// that is, it prints the end of the line for all lines.614template <typename... Args> struct print_cols {615 std::string s_;616617 print_cols(const Args &...args) {618 static_assert(619 ((detail::is_container<std::decay_t<Args>>::value or620 detail::is_sequential<std::decay_t<Args>>::value) and621 ...),622 "print_cols: arguments must be containers or sequential generator "623 "values");624 std::ostringstream oss;625 write(oss, args...);626 s_ = oss.str();627 }628629 void write(std::ostream &os, const Args &...args) {630 auto views = std::apply(631 [](const Args &...inner_args) {632 return std::make_tuple(633 detail::print_cols_view<decltype(inner_args)>{634 inner_args}...);635 },636 std::forward_as_tuple(args...));637638 const std::size_t n = std::get<0>(views).size();639640 auto check = [&](const auto &v) {641 tgen_ensure(v.size() == n, "print_cols: sizes should be the same");642 };643 std::apply([&](const auto &...v) { (check(v), ...); }, views);644645 for (std::size_t i = 0; i < n; ++i) {646 bool first = true;647648 std::apply(649 [&](const auto &...v) {650 ((os << (first ? "" : " ") << print(v.get(i)),651 first = false),652 ...);653 },654 views);655656 os << '\n';657658 std::apply([](auto &...v) { (v.advance(), ...); }, views);659 }660 }661662 friend std::ostream &operator<<(std::ostream &out, const print_cols &pr) {663 return out << pr.s_;664 }665};666667/*668 * Global random operations.669 */670671namespace detail {672673// libstdc++ accepts std::uniform_int_distribution with narrow integral types674// (char/signed char/unsigned char/short/bool), but libc++ rejects them with a675// hard static_assert ("IntType must be a supported integer type"). Promote such676// types to a width the standard guarantees, preserving signedness, so the same677// `next<T>` works across both standard libraries (e.g. Apple clang / libc++).678template <typename T>679using uniform_int_t = std::conditional_t<680 (sizeof(T) >= sizeof(short)), T,681 std::conditional_t<std::is_signed_v<T>, int, unsigned int>>;682683} // namespace detail684685// Returns a uniformly random number in [0, right)686// O(1).687template <typename T> T next(T right) {688 detail::ensure_registered();689 if constexpr (std::is_integral_v<T>) {690 tgen_ensure(right >= 1, "value for `next` must be valid");691 return static_cast<T>(692 std::uniform_int_distribution<detail::uniform_int_t<T>>(693 0,694 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));695 } else if constexpr (std::is_floating_point_v<T>) {696 tgen_ensure(right >= 0, "value for `next` must be valid");697 return std::uniform_real_distribution<T>(0, right)(detail::rng);698 } else699 throw detail::error("invalid type for next (" +700 std::string(typeid(T).name()) + ")");701}702703// Returns a uniformly random number in [left, right].704// For floating-point types, uses uniform_real_distribution ([left, right) in705// C++), equivalent to [left, right] because the right endpoint has probability706// zero.707// O(1).708template <typename T> T next(T left, T right) {709 detail::ensure_registered();710 tgen_ensure(left <= right, "range for `next` must be valid");711 if constexpr (std::is_integral_v<T>)712 return static_cast<T>(713 std::uniform_int_distribution<detail::uniform_int_t<T>>(714 static_cast<detail::uniform_int_t<T>>(left),715 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));716 else if constexpr (std::is_floating_point_v<T>)717 return std::uniform_real_distribution<T>(left, right)(detail::rng);718 else719 throw detail::error("invalid type for next (" +720 std::string(typeid(T).name()) + ")");721}722723// Skewed next.724//725// Returns a random number in [0, right) with a bias controlled by `w`.726// - w = 0:727// Uniform distribution.728// - w > 0:729// Returns the maximum of (w + 1) independent uniform samples.730// Biases the distribution toward larger values.731// The resulting density is proportional to:732// f(x) = x^w733// In particular:734// w = 1 -> linear bias735// w = 2 -> quadratic bias736// w = 3 -> cubic bias737// - w < 0:738// Returns the minimum of (-w + 1) independent uniform samples.739// Symmetric to the w > 0 case.740// The continuous version corresponds to Beta distributions:741// w > 0 -> Beta(w + 1, 1)742// w < 0 -> Beta(1, -w + 1)743// For |w| > 5, the distribution is approximate.744// O(1).745template <typename T> T wnext(T right, int w) {746 // For small |w|, use the naive approach.747 if (abs(w) <= 5) {748 T val = next<T>(right);749 for (int i = 0; i < w; ++i)750 val = std::max(val, next<T>(right));751 for (int i = 0; i < -w; ++i)752 val = std::min(val, next<T>(right));753 return val;754 }755756 // O(1) way.757 double x, r = next<double>(0, 1);758759 if (w >= 0) {760 x = std::pow(r, 1.0 / (w + 1));761 } else {762 x = 1.0 - std::pow(r, 1.0 / (-w + 1));763 }764765 return T(x * right);766}767768// Returns a random number in [left, right] with a bias controlled by `w`.769// O(1).770template <typename T> T wnext(T left, T right, int w) {771 // For small |w|, use the naive approach.772 if (abs(w) <= 5) {773 T val = next<T>(left, right);774 for (int i = 0; i < w; ++i)775 val = std::max(val, next<T>(left, right));776 for (int i = 0; i < -w; ++i)777 val = std::min(val, next<T>(left, right));778 return val;779 }780781 // O(1) way.782 double x, r = next<double>(0, 1);783784 if (w >= 0) {785 x = std::pow(r, 1.0 / (w + 1));786 } else {787 x = 1.0 - std::pow(r, 1.0 / (-w + 1));788 }789790 return left + T(x * (right - left));791}792793namespace detail {794795// Uniformly random 128 bit number in [0, total).796// O(1) expected.797inline u128 next128(u128 total) {798 tgen_ensure(total > 0, "next128: total must be positive");799800 // Largest multiple of total less than 2^128.801 u128 limit = (u128(-1) / total) * total;802803 while (true) {804 // Generate uniform 128-bit random number.805 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))806 << 64) |807 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());808809 if (r < limit)810 return r % total;811 }812}813814} // namespace detail815816// Weighted sampler.817//818// Generates indices with probability proportional to `distribution`, using819// alias method.820//821// Internally, integral weights are accumulated in unsigned __int128 (exact);822// floating-point weights are accumulated in double.823// <O(n), O(1)>.824template <typename T> struct weighted_sampler {825 static_assert(std::is_arithmetic_v<T>,826 "weighted_sampler requires an arithmetic weight type");827828 // Internal storage type: `u128` for integral inputs (exact arithmetic),829 // `double` for floating-point inputs.830 using storage_t =831 std::conditional_t<std::is_integral_v<T>, detail::u128, double>;832833 int n_;834 std::vector<storage_t> weight_;835 std::vector<int> alias_;836 storage_t total_;837838 // Creates an alias method for generating indices with probability839 // proportional to the distribution.840 // O(n).841 weighted_sampler(const std::vector<T> &distribution)842 : n_(distribution.size()), alias_(n_) {843 tgen_ensure(distribution.size() > 0,844 "weighted_sampler: distribution must be non-empty");845 for (const auto &w : distribution)846 tgen_ensure(w >= 0,847 "weighted_sampler: distribution must be non-negative");848849 total_ = std::accumulate(distribution.begin(), distribution.end(),850 storage_t(0));851852 std::queue<int> big, small;853 for (int i = 0; i < n_; ++i) {854 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));855 if (weight_[i] < total_)856 small.push(i);857 else858 big.push(i);859 }860861 while (!small.empty() and !big.empty()) {862 int s = small.front();863 small.pop();864 int b = big.front();865 big.pop();866867 alias_[s] = b;868869 weight_[b] -= total_ - weight_[s];870 if (weight_[b] < total_)871 small.push(b);872 else873 big.push(b);874 }875876 detail::tgen_ensure_against_bug(877 small.empty(), "weighted_sampler: small must be empty");878879 // The remaining elements should have weight equal to total and be880 // assigned to themselves.881 while (!big.empty()) {882 int b = big.front();883 big.pop();884 if constexpr (std::is_integral_v<T>) {885 detail::tgen_ensure_against_bug(886 weight_[b] == total_,887 "weighted_sampler: weight of big element must be total");888 }889 alias_[b] = b;890 }891 }892 weighted_sampler(const std::initializer_list<T> &distribution)893 : weighted_sampler(std::vector<T>(distribution)) {}894895 // Uniformly random value in [0, total). Overloaded so next() can dispatch896 // at compile time to the right primitive for the chosen `storage_t`.897 static detail::u128 sample_below(detail::u128 total) {898 return detail::next128(total);899 }900 static double sample_below(double total) {901 return tgen::next<double>(0, total);902 }903904 // Generates a random index with probability proportional to the905 // distribution.906 // O(1).907 size_t next() const {908 int i = tgen::next<int>(0, n_ - 1);909 return sample_below(total_) < weight_[i] ? i : alias_[i];910 }911};912template <typename T>913weighted_sampler(const std::vector<T> &) -> weighted_sampler<T>;914template <typename T>915weighted_sampler(const std::initializer_list<T> &) -> weighted_sampler<T>;916917// Returns i with probability proportional to distribution[i].918// O(|distribution|).919template <typename T>920size_t next_by_distribution(const std::vector<T> &distribution) {921 return weighted_sampler(distribution).next();922}923template <typename T>924size_t next_by_distribution(const std::initializer_list<T> &distribution) {925 return next_by_distribution(std::vector<T>(distribution));926}927928// Returns a vector of k indices with probability proportional to929// `distribution`. Uses alias method.930// O(k + |distribution|).931template <typename T>932std::vector<int> many_by_distribution(int k,933 const std::vector<T> &distribution) {934 tgen_ensure(distribution.size() > 0, "distribution must be non-empty");935 tgen_ensure(k >= 0, "number of elements to choose must be non-negative");936937 weighted_sampler am(distribution);938 std::vector<int> res;939 for (int i = 0; i < k; ++i)940 res.push_back(am.next());941 return res;942}943template <typename T>944std::vector<int>945many_by_distribution(int k, const std::initializer_list<T> &distribution) {946 return many_by_distribution(k, std::vector<T>(distribution));947}948949// Shuffles [first, last) inplace uniformly, for RandomAccessIterator.950// O(|container|).951template <typename It> void shuffle(It first, It last) {952 if (first == last)953 return;954955 for (It i = first + 1; i != last; ++i)956 std::iter_swap(i, first + next(0, static_cast<int>(i - first)));957}958959// Shuffles container uniformly.960// O(|container|).961template <typename C> [[nodiscard]] auto shuffled(const C &container) {962 if constexpr (detail::is_associative_container<C>::value) {963 std::vector<typename C::value_type> vec(container.begin(),964 container.end());965 shuffle(vec.begin(), vec.end());966 return vec;967 } else {968 auto new_container = container;969 shuffle(new_container.begin(), new_container.end());970 return new_container;971 }972}973template <typename T>974[[nodiscard]] std::vector<T> shuffled(const std::initializer_list<T> &il) {975 return shuffled(std::vector<T>(il));976}977978// Returns a random element from [first, last) uniformly.979// O(1) for random_access_iterator, O(|last - first|) otherwise.980template <typename It> typename It::value_type pick(It first, It last) {981 int size = std::distance(first, last);982 tgen_ensure(size > 0, "cannot pick from empty range");983 It it = first;984 std::advance(it, next(0, size - 1));985 return *it;986}987988// Returns a random element from container uniformly.989// O(1) for random_access_iterator, O(|container|) otherwise.990template <typename C> typename C::value_type pick(const C &container) {991 return pick(container.begin(), container.end());992}993template <typename T> T pick(const std::initializer_list<T> &il) {994 return pick(std::vector<T>(il));995}996997// Returns container[i] with probability proportional to distribution[i].998// O(1) for random_access_iterator, O(|container|) otherwise.999template <typename C, typename T>1000typename C::value_type pick_by_distribution(const C &container,1001 std::vector<T> distribution) {1002 tgen_ensure(container.size() == distribution.size(),1003 "container and distribution must have the same size");1004 auto it = container.begin();1005 std::advance(it, next_by_distribution(distribution));1006 return *it;1007}1008template <typename C, typename T>1009typename C::value_type1010pick_by_distribution(const C &container,1011 const std::initializer_list<T> &distribution) {1012 return pick_by_distribution(container, std::vector<T>(distribution));1013}1014template <typename T, typename U>1015T pick_by_distribution(const std::initializer_list<T> &il,1016 const std::vector<U> &distribution) {1017 return pick_by_distribution(std::vector<T>(il), distribution);1018}1019template <typename T, typename U>1020T pick_by_distribution(const std::initializer_list<T> &il,1021 const std::initializer_list<U> &distribution) {1022 return pick_by_distribution(std::vector<T>(il),1023 std::vector<U>(distribution));1024}10251026// Chooses k values uniformly from container, as in a subsequence of size k.1027// Returns a copy. O(|container|).1028template <typename C> C choose(const C &container, int k) {1029 tgen_ensure(0 < k and k <= static_cast<int>(container.size()),1030 "number of elements to choose must be valid");1031 std::vector<typename C::value_type> new_vec;1032 C new_container;1033 int need = k, left = container.size();1034 for (auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {1035 if (next(1, left--) <= need) {1036 new_container.insert(new_container.end(), *cur_it);1037 need--;1038 }1039 }1040 return new_container;1041}1042template <typename T>1043std::vector<T> choose(const std::initializer_list<T> &il, int k) {1044 return choose(std::vector<T>(il), k);1045}10461047// Number distinct generator for integral types.1048// Optimized for performance (unordered_map virtual list; gen_list uses array1049// pool, complement, or sparse sampling).1050template <typename T> struct distinct_range {1051 T left_, right_;1052 T num_available_;1053 std::unordered_map<T, T> virtual_list_;10541055 // When the range fits in memory, sample via array Fisher–Yates.1056 static constexpr size_t array_pool_max = size_t{1} << 23;10571058 // Generator of distinct values in [left, right].1059 distinct_range(T left, T right)1060 : left_(left), right_(right), num_available_(right - left + 1) {}10611062 // Returns the number of distinct values left to generate.1063 T size() const { return num_available_; }10641065 // Generates a random value in [left_, right_] that has not been generated1066 // yet.1067 // O(log n).1068 T gen() {1069 // One iteration of Fisher–Yates.1070 tgen_ensure(size() > 0, "distinct_range: no more values to generate");10711072 T i = next<T>(0, size() - 1);1073 T j = size() - 1;10741075 auto vi_it = virtual_list_.find(i);1076 T vi = vi_it == virtual_list_.end() ? i : vi_it->second;1077 auto vj_it = virtual_list_.find(j);1078 T vj = vj_it == virtual_list_.end() ? j : vj_it->second;1079 virtual_list_[i] = vj;10801081 --num_available_;10821083 return vi + left_;1084 }10851086 // Generates a list of distinct values.1087 // Optimized for performance (array pool, complement, or sparse sampling).1088 // O(size) when the range fits in memory; O(size log range) otherwise.1089 auto gen_list(int count) {1090 tgen_ensure(count >= 0, "distinct_range: size must be nonnegative");1091 tgen_ensure(count <= num_available_,1092 "distinct_range: no more values to generate");10931094 size_t range_size = right_ - left_ + 1;1095 size_t sample_count = count;10961097 std::vector<T> res;1098 if (sample_count > 0) {1099 if (range_size <= array_pool_max)1100 res = sample_from_pool(sample_count, range_size);1101 else if (sample_count * 2 > range_size)1102 res = sample_complement(sample_count, range_size);1103 else1104 res = sample_sparse(sample_count);1105 }11061107 num_available_ -= count;1108 virtual_list_.clear();1109 return typename list<T>::value(res);1110 }11111112 // Generates all distinct values.1113 // O(n) when the range fits in memory; O(n log n) otherwise.1114 auto gen_all() { return gen_list(size()); }11151116 private:1117 // Samples count distinct values via array Fisher–Yates on [left_, right_].1118 // O(range_size) time and memory.1119 std::vector<T> sample_from_pool(size_t count, size_t range_size) {1120 std::vector<T> pool(range_size);1121 std::iota(pool.begin(), pool.end(), left_);1122 for (size_t i = 0; i < count; ++i) {1123 size_t j = next<size_t>(i, range_size - 1);1124 std::swap(pool[i], pool[j]);1125 }1126 pool.resize(count);1127 return pool;1128 }11291130 // Samples count distinct values by excluding range_size - count values.1131 // O(range_size + (range_size - count) log(range_size)).1132 std::vector<T> sample_complement(size_t count, size_t range_size) {1133 size_t exclude_count = range_size - count;1134 std::unordered_set<T> excluded;1135 excluded.reserve(exclude_count * 2);11361137 if (exclude_count <= array_pool_max) {1138 for (T value : sample_from_pool(exclude_count, range_size))1139 excluded.insert(value);1140 } else {1141 for (T value : sample_sparse(exclude_count))1142 excluded.insert(value);1143 }11441145 std::vector<T> res;1146 res.reserve(count);1147 for (T value = left_; value <= right_; ++value) {1148 if (!excluded.count(value))1149 res.push_back(value);1150 }1151 detail::tgen_ensure_against_bug(1152 res.size() == count, "distinct_range: complement sampling failed");1153 return res;1154 }11551156 // Samples count distinct values via sparse-map Fisher–Yates.1157 // O(count log(range_size)).1158 std::vector<T> sample_sparse(size_t count) {1159 std::unordered_map<T, T> local_virtual;1160 local_virtual.reserve(count * 2);1161 T remaining = range_span();1162 std::vector<T> res;1163 res.reserve(count);1164 for (size_t step = 0; step < count; ++step) {1165 T i = next<T>(0, remaining - 1);1166 T j = remaining - 1;11671168 auto vi_it = local_virtual.find(i);1169 T vi = vi_it == local_virtual.end() ? i : vi_it->second;1170 auto vj_it = local_virtual.find(j);1171 T vj = vj_it == local_virtual.end() ? j : vj_it->second;1172 local_virtual[i] = vj;11731174 res.push_back(vi + left_);1175 --remaining;1176 }1177 return res;1178 }11791180 // Returns right_ - left_ + 1.1181 // O(1).1182 T range_span() { return right_ - left_ + 1; }1183};11841185// Distinct generator for containers.1186template <typename T> struct distinct_container {1187 std::vector<T> list_;1188 distinct_range<size_t> idx_;11891190 // Creates a distinct container generator for the given container.1191 template <typename C>1192 distinct_container(const C &container)1193 : list_(container.begin(), container.end()),1194 idx_(0, static_cast<int>(container.size()) - 1) {}1195 distinct_container(const std::initializer_list<T> &il)1196 : distinct_container(std::vector<T>(il)) {}11971198 // Returns the number of distinct elements left to generate.1199 size_t size() const { return idx_.size(); }12001201 // Generates a random element from container uniformly.1202 // O(log n).1203 T gen() { return list_[idx_.gen()]; }12041205 // Generates a list of distinct values.1206 // O(size * log(n)).1207 auto gen_list(int size) {1208 std::vector<T> res;1209 for (int i = 0; i < size; ++i)1210 res.push_back(gen());1211 return typename list<T>::value(res);1212 }12131214 // Generates all distinct values.1215 // O(n log(n))1216 auto gen_all() {1217 std::vector<T> res;1218 while (size() > 0)1219 res.push_back(gen());1220 return typename list<T>::value(res);1221 }1222};1223template <typename C>1224distinct_container(const C &) -> distinct_container<typename C::value_type>;12251226/************1227 * *1228 * OPTS *1229 * *1230 ************/12311232/*1233 * Opts - options given to the generator.1234 *1235 * Incompatible with testlib.1236 *1237 * Opts are a list of either positional or named options.1238 *1239 * Named options are given in one of the following formats:1240 * 1) -keyname=value or --keyname=value (ex. -n=10 , --test-count=20)1241 * 2) -keyname value or --keyname value (ex. -n 10 , --test-count 20)1242 *1243 * Positional options are numbered from 0 sequentially.1244 * For example, for "10 -n=20 str" positional option 1 is the string "str".1245 */12461247/*1248 * C++ version selection.1249 */12501251// Sets C++ version.1252inline void set_cpp_version(int version) {1253 detail::cpp = detail::cpp_value(version);1254}12551256/*1257 * Compiler selection.1258 */12591260// GCC compiler type.1261inline compiler_value gcc(int major = 0, int minor = 0) {1262 return {compiler_kind::gcc, major, minor};1263}12641265// Clang compiler type.1266inline compiler_value clang(int major = 0, int minor = 0) {1267 return {compiler_kind::clang, major, minor};1268}12691270// Sets compiler.1271inline void set_compiler(compiler_value compiler) {1272 detail::compiler.kind_ = compiler.kind_;1273 detail::compiler.major_ = compiler.major_;1274 detail::compiler.minor_ = compiler.minor_;1275}12761277namespace detail {12781279// Processes special opt flags.1280// Returns true if the key is a special opt flag.1281inline bool process_special_opt_flags(std::string &key) {1282 // Checks for gen::CPP=17|20|231283 if (key.find("tgen::CPP:") == 0) {1284 int prefix_len = std::string("tgen::CPP:").size();1285 tgen_ensure(static_cast<int>(key.size()) == prefix_len + 2 and1286 std::isdigit(key[prefix_len]) and1287 std::isdigit(key[prefix_len + 1]),1288 "invalid CPP format");1289 int version = std::stoi(key.substr(prefix_len, 2));1290 set_cpp_version(version);1291 return true;1292 }12931294 // Checks for tgen::(GCC|CLANG) or1295 // tgen::(GCC|CLANG):(version|version.minor).1296 compiler_kind kind;1297 size_t prefix_len = 0;12981299 if (key.find("tgen::GCC") == 0) {1300 kind = compiler_kind::gcc;1301 prefix_len = std::string("tgen::GCC").size();1302 } else if (key.find("tgen::CLANG") == 0) {1303 kind = compiler_kind::clang;1304 prefix_len = std::string("tgen::CLANG").size();1305 } else {1306 return false;1307 }13081309 if (key.size() == prefix_len) {1310 set_compiler(compiler_value(kind, 0, 0));1311 return true;1312 }13131314 tgen_ensure(key[prefix_len] == ':', "invalid compiler format");1315 ++prefix_len; // for ':'.13161317 std::string inside = key.substr(prefix_len, key.size() - prefix_len);1318 int major = 0, minor = 0;13191320 size_t dot = inside.find('.');1321 if (dot == std::string::npos) {1322 tgen_ensure(!inside.empty() and1323 std::all_of(inside.begin(), inside.end(), ::isdigit),1324 "invalid compiler version");1325 major = std::stoi(inside);1326 } else {1327 std::string maj = inside.substr(0, dot);1328 std::string min = inside.substr(dot + 1);13291330 tgen_ensure(!maj.empty() and1331 std::all_of(maj.begin(), maj.end(), ::isdigit) and1332 maj.size() <= 3,1333 "invalid compiler major version");1334 tgen_ensure(!min.empty() and1335 std::all_of(min.begin(), min.end(), ::isdigit) and1336 min.size() <= 3,1337 "invalid compiler minor version");13381339 major = std::stoi(maj);1340 minor = std::stoi(min);1341 }13421343 set_compiler(compiler_value(kind, major, minor));13441345 return true;1346}13471348inline std::vector<std::string>1349 pos_opts; // Dictionary containing the positional parsed opts.1350inline std::map<std::string, std::string>1351 named_opts; // Global dictionary the named parsed opts.13521353template <typename T> T get_opt(const std::string &value) {1354 try {1355 if constexpr (std::is_same_v<T, bool>) {1356 if (value == "true" or value == "1")1357 return true;1358 if (value == "false" or value == "0")1359 return false;1360 } else if constexpr (std::is_integral_v<T>) {1361 if constexpr (std::is_unsigned_v<T>)1362 return static_cast<T>(std::stoull(value));1363 else1364 return static_cast<T>(std::stoll(value));1365 } else if constexpr (std::is_floating_point_v<T>)1366 return static_cast<T>(std::stold(value));1367 else1368 return value; // Default: std::string.1369 } catch (...) {1370 }13711372 throw error("invalid value `" + value + "` for type " + typeid(T).name());1373}13741375inline void parse_opts(int argc, char **argv) {1376 // Parses the opts into `pos_opts` vector and `named_opts`1377 // map. Starting from 1 to ignore the name of the executable.1378 for (int i = 1; i < argc; ++i) {1379 std::string key(argv[i]);13801381 if (process_special_opt_flags(key))1382 continue;13831384 if (key[0] == '-') {1385 tgen_ensure(key.size() > 1,1386 "invalid opt (" + std::string(argv[i]) + ")");1387 if ('0' <= key[1] and key[1] <= '9') {1388 // This case is a positional negative number argument.1389 pos_opts.push_back(key);1390 continue;1391 }13921393 // Pops first char '-'.1394 key = key.substr(1);1395 } else {1396 // This case is a positional argument that does not start with '-'.1397 pos_opts.push_back(key);1398 continue;1399 }14001401 // Pops a possible second char '-'.1402 if (key[0] == '-') {1403 tgen_ensure(key.size() > 1,1404 "invalid opt (" + std::string(argv[i]) + ")");14051406 // Pops first char '-'.1407 key = key.substr(1);1408 }14091410 // Assumes that, if it starts with '-' and second char is not a digit,1411 // then it is a <key, value> pair.1412 // 1 or 2 chars '-' have already been popped.14131414 std::size_t eq = key.find('=');1415 if (eq != std::string::npos) {1416 // This is the '--key=value' case.1417 std::string value = key.substr(eq + 1);1418 key = key.substr(0, eq);1419 tgen_ensure(!key.empty() and !value.empty(),1420 "expected non-empty key/value in opt (" +1421 std::string(argv[i]) + ")");1422 tgen_ensure(named_opts.count(key) == 0,1423 "cannot have repeated keys");1424 named_opts[key] = value;1425 } else {1426 // This is the '--key value' case.1427 tgen_ensure(named_opts.count(key) == 0,1428 "cannot have repeated keys");1429 tgen_ensure(argv[i + 1], "value cannot be empty");1430 named_opts[key] = std::string(argv[i + 1]);1431 ++i;1432 }1433 }1434}14351436inline void set_seed(int argc, char **argv) {1437 std::vector<uint32_t> seed;14381439 // Starting from 1 to ignore the name of the executable.1440 for (int i = 1; i < argc; ++i) {1441 // We append the number of chars, and then the list of chars.1442 int size_pos = seed.size();1443 seed.push_back(0);1444 for (char *s = argv[i]; *s != '\0'; ++s) {1445 ++seed[size_pos];1446 seed.push_back(*s);1447 }1448 }1449 std::seed_seq seq(seed.begin(), seed.end());1450 rng.seed(seq);1451}14521453} // namespace detail14541455// Returns true if there is an opt at a given index.1456inline bool has_opt(std::size_t index) {1457 detail::ensure_registered();1458 return index < detail::pos_opts.size();1459}14601461// Returns true if there is an opt with a given key.1462inline bool has_opt(const std::string &key) {1463 detail::ensure_registered();1464 return detail::named_opts.count(key) != 0;1465}1466template <typename K>1467std::enable_if_t<std::is_same_v<K, char>, bool> has_opt(K key) {1468 return has_opt(std::string(1, key));1469}14701471// Returns the parsed opt by a given index. If no opts with the given index are1472// found, returns the given default_value.1473template <typename T>1474T opt(size_t index, std::optional<T> default_value = std::nullopt) {1475 detail::ensure_registered();1476 if (!has_opt(index)) {1477 if (default_value)1478 return *default_value;1479 throw detail::error("cannot find opt at index " +1480 std::to_string(index));1481 }1482 return detail::get_opt<T>(detail::pos_opts[index]);1483}14841485// Returns the parsed opt by a given key. If no opts with the given key are1486// found, returns the given default_value.1487template <typename T>1488T opt(const std::string &key, std::optional<T> default_value = std::nullopt) {1489 detail::ensure_registered();1490 if (!has_opt(key)) {1491 if (default_value)1492 return *default_value;1493 throw detail::error("cannot find opt with key " + key);1494 }1495 return detail::get_opt<T>(detail::named_opts[key]);1496}1497template <typename T, typename K>1498std::enable_if_t<std::is_same_v<K, char>, T>1499opt(K key, std::optional<T> default_value = std::nullopt) {1500 return opt<T>(std::string(1, key), default_value);1501}15021503// Registers generator by initializing rng and parsing opts.1504inline void register_gen(int argc, char **argv) {1505 detail::set_seed(argc, argv);15061507 detail::pos_opts.clear();1508 detail::named_opts.clear();1509 detail::parse_opts(argc, argv);15101511 detail::registered = true;1512}15131514// Registers generator by initializing rng with a given seed.1515inline void register_gen(std::optional<long long> seed = std::nullopt) {1516 if (seed)1517 detail::rng.seed(*seed);1518 else1519 detail::rng.seed();15201521 detail::pos_opts.clear();1522 detail::named_opts.clear();15231524 detail::registered = true;1525}15261527/************1528 * *1529 * LIST *1530 * *1531 ************/15321533/*1534 * List generator.1535 *1536 * List of integral types.1537 */15381539template <typename T> struct list : gen_base<list<T>> {1540 int size_; // Size of list.1541 T value_l_, value_r_; // Range of defined values.1542 std::set<T> values_; // Set of values. If empty, use range; if not,1543 // represents the possible values, and the range1544 // represents the index in this set.1545 std::map<T, int>1546 value_idx_in_set_; // Index of every value in the set above.1547 mutable std::vector<std::pair<T, T>>1548 val_range_; // Range of values of each index.1549 mutable std::vector<std::vector<int>> neigh_; // Adjacency list of equality.1550 std::vector<std::set<int>>1551 diff_restrictions_; // All different restrictions.1552 bool index_constraints_{1553 false}; // True after fix/equal narrows per-index generation.1554 mutable bool uses_full_range_{1555 false}; // If true, every index uses [value_l_, value_r_] lazily.15561557 // Creates generator for lists of size 'size', with random T in [value_left,1558 // value_right].1559 list(int size, T value_left, T value_right)1560 : size_(size), value_l_(value_left), value_r_(value_right),1561 uses_full_range_(true) {1562 tgen_ensure(size_ > 0, "list: size must be positive");1563 tgen_ensure(value_l_ <= value_r_, "list: value range must be valid");1564 }15651566 // Creates list with value set.1567 list(int size, std::set<T> values)1568 : size_(size), values_(values), index_constraints_(true) {1569 tgen_ensure(size_ > 0, "list: size must be positive");1570 tgen_ensure(!values.empty(), "list: value set must be non-empty");1571 value_l_ = 0, value_r_ = values.size() - 1;1572 val_range_.assign(size_, {value_l_, value_r_});1573 int idx = 0;1574 for (T val : values_)1575 value_idx_in_set_[val] = idx++;1576 }15771578 // Restricts lists for list[idx] = val.1579 list &fix(int idx, T val) {1580 tgen_ensure(0 <= idx and idx < size_, "list: index must be valid");1581 ensure_val_range_materialized();1582 if (values_.size() == 0) {1583 auto &[left, right] = val_range_[idx];1584 if (left == right and value_l_ != value_r_) {1585 tgen_ensure(left == val,1586 "list: must not set to two different values");1587 } else {1588 tgen_ensure(left <= val and val <= right,1589 "list: value must be in the defined range");1590 }1591 left = right = val;1592 } else {1593 tgen_ensure(values_.count(val),1594 "list: value must be in the set of values");1595 auto &[left, right] = val_range_[idx];1596 int new_val = value_idx_in_set_[val];1597 tgen_ensure(left <= new_val and new_val <= right,1598 "list: must not set to two different values");1599 left = right = new_val;1600 }1601 index_constraints_ = true;1602 return *this;1603 }16041605 // Restricts lists for list[idx_1] = list[idx_2].1606 list &equal(int idx_1, int idx_2) {1607 tgen_ensure(0 <= std::min(idx_1, idx_2) and1608 std::max(idx_1, idx_2) < size_,1609 "list: indices must be valid");1610 if (idx_1 == idx_2)1611 return *this;16121613 ensure_val_range_materialized();1614 ensure_neigh_allocated();1615 index_constraints_ = true;1616 neigh_[idx_1].push_back(idx_2);1617 neigh_[idx_2].push_back(idx_1);1618 return *this;1619 }16201621 // Restricts lists for list[S] to be equal, for given subset S of indices.1622 list &equal(std::set<int> indices) {1623 if (!indices.empty()) {1624 std::set<int>::iterator beg = indices.begin();1625 for (auto it = std::next(beg); it != indices.end(); ++it)1626 equal(*beg, *it);1627 }1628 return *this;1629 }16301631 // Restricts lists for list[left..right] to have all equal values.1632 list &equal_range(int left, int right) {1633 tgen_ensure(0 <= left and left <= right and right < size_,1634 "list: range indices must be valid");1635 for (int i = left; i < right; ++i)1636 equal(i, i + 1);1637 return *this;1638 }16391640 // Restricts lists for all equal elements.1641 list &all_equal() { return equal_range(0, size_ - 1); }16421643 // Restricts lists for list[S] to be different (distinct), for given subset1644 // S of indices. You cannot add two of these restrictions on sets that1645 // intersect.1646 list &different(std::set<int> indices) {1647 if (!indices.empty())1648 diff_restrictions_.push_back(indices);1649 return *this;1650 }16511652 // Restricts lists for list[idx_1] != list[idx_2].1653 list &different(int idx_1, int idx_2) {1654 std::set<int> indices = {idx_1, idx_2};1655 return different(indices);1656 }16571658 // Restricts lists for list[left..right] to have all different values.1659 list &different_range(int left, int right) {1660 tgen_ensure(0 <= left and left <= right and right < size_,1661 "list: range indices must be valid");1662 std::vector<int> indices(right - left + 1);1663 std::iota(indices.begin(), indices.end(), left);1664 return different(std::set<int>(indices.begin(), indices.end()));1665 }16661667 // Restricts lists for all different elements.1668 list &all_different() {1669 std::vector<int> indices(size_);1670 std::iota(indices.begin(), indices.end(), 0);1671 return different(std::set<int>(indices.begin(), indices.end()));1672 }16731674 // List value.1675 // Operations on a value are not random.1676 struct value : gen_value_base<value> {1677 using tgen_is_sequential_tag = detail::is_sequential_tag;16781679 using value_type = T; // Value type, for templates.1680 using std_type = std::vector<T>; // std type for value.16811682 std::vector<T> vec_; // list.1683 char sep_; // Separator for printing.16841685 value(const std::vector<T> &vec) : vec_(vec), sep_(' ') {}1686 value(const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}16871688 // Fetches size.1689 int size() const { return vec_.size(); }16901691 // Fetches position idx.1692 T &operator[](int idx) {1693 tgen_ensure(0 <= idx and idx < size(),1694 "list: value: index out of bounds");1695 return vec_[idx];1696 }1697 const T &operator[](int idx) const {1698 tgen_ensure(0 <= idx and idx < size(),1699 "list: value: index out of bounds");1700 return vec_[idx];1701 }17021703 // Sorts values in non-decreasing order.1704 // O(n log n).1705 value &sort() {1706 std::sort(vec_.begin(), vec_.end());1707 return *this;1708 }17091710 // Reverses list.1711 // O(n).1712 value &reverse() {1713 std::reverse(vec_.begin(), vec_.end());1714 return *this;1715 }17161717 // Sets the separator for the list, for printing.1718 // O(1).1719 value &separator(char sep) {1720 sep_ = sep;1721 return *this;1722 }17231724 // Concatenates two values.1725 // Linear.1726 value operator+(const value &rhs) const {1727 std::vector<T> new_vec = vec_;1728 for (int i = 0; i < rhs.size(); ++i)1729 new_vec.push_back(rhs[i]);1730 return value(new_vec);1731 }17321733 // Shuffles list uniformly.1734 // O(n).1735 value &shuffle() {1736 for (int i = 0; i < size(); ++i)1737 std::swap(vec_[i], vec_[next(0, size() - 1)]);1738 return *this;1739 }17401741 // Returns a random element uniformly.1742 // O(1).1743 T pick() const { return vec_[next<int>(0, size() - 1)]; }17441745 // Returns vec_[i] with probability proportional to distribution[i].1746 // O(1).1747 template <typename Dist>1748 T pick_by_distribution(const std::vector<Dist> &distribution) const {1749 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),1750 "value and distribution must have the same size");1751 return vec_[next_by_distribution(distribution)];1752 }1753 template <typename Dist>1754 T pick_by_distribution(1755 const std::initializer_list<Dist> &distribution) const {1756 return pick_by_distribution(std::vector<Dist>(distribution));1757 }17581759 // Chooses k values uniformly, as in a subsequence of size k.1760 // O(n).1761 value choose(int k) const {1762 tgen_ensure(0 < k and k <= size(),1763 "number of elements to choose must be valid");1764 std::vector<T> new_vec;1765 int need = k;1766 for (int i = 0; need > 0; ++i) {1767 int left = size() - i;1768 if (next(1, left) <= need) {1769 new_vec.push_back(vec_[i]);1770 need--;1771 }1772 }1773 return value(new_vec);1774 }17751776 // Prints to std::ostream, separated by sep_.1777 friend std::ostream &operator<<(std::ostream &out, const value &val) {1778 for (int i = 0; i < val.size(); ++i) {1779 if (i > 0)1780 out << val.sep_;1781 out << val[i];1782 }1783 return out;1784 }17851786 // Gets a std::vector representing the value.1787 auto to_std() const {1788 if constexpr (!detail::is_generator_value<T>::value) {1789 return vec_;1790 } else {1791 std::vector<typename T::std_type> vec;1792 for (const auto &i : vec_)1793 vec.push_back(i.to_std());1794 return vec;1795 }1796 }1797 };17981799 // Generates list value.1800 // Optimized for performance (unconstrained and all-different fast paths).1801 // O(n log n).1802 value gen() const {1803 if (diff_restrictions_.empty()) {1804 if (auto unconstrained = try_gen_unconstrained())1805 return *unconstrained;1806 }1807 if (auto all_different = try_gen_all_different())1808 return *all_different;18091810 ensure_neigh_allocated();1811 std::vector<T> vec(size_);1812 std::vector<bool> defined_idx(1813 size_, false); // For every index, if it has been set in `vec`.18141815 std::vector<int> comp_id(size_, -1); // Component id of each index.1816 std::vector<std::vector<int>> comp(size_); // Component of each comp-id.1817 int comp_count = 0; // Number of different components.18181819 // Defines value of entire component.1820 auto define_comp = [&](int cur_comp, T val) {1821 for (int idx : comp[cur_comp]) {1822 tgen_ensure(!defined_idx[idx]);1823 vec[idx] = val;1824 defined_idx[idx] = true;1825 }1826 };18271828 // Groups = components.1829 {1830 std::vector<bool> vis(size_, false); // Visited for each index.1831 for (int idx = 0; idx < size_; ++idx)1832 if (!vis[idx]) {1833 T new_value;1834 bool value_defined = false;18351836 // BFS to visit the connected component, grouping equal1837 // values.1838 std::queue<int> q({idx});1839 vis[idx] = true;1840 std::vector<int> component;1841 while (!q.empty()) {1842 int cur_idx = q.front();1843 q.pop();18441845 component.push_back(cur_idx);18461847 // Checks value.1848 auto [l, r] = val_range_at(cur_idx);1849 if (l == r) {1850 if (!value_defined) {1851 // We found the value.1852 value_defined = true;1853 new_value = l;1854 } else if (new_value != l) {1855 // We found a contradiction1856 throw detail::contradiction_error(1857 "list",1858 "tried to set value to `" +1859 std::to_string(new_value) +1860 "`, but it was already set as `" +1861 std::to_string(l) + "`");1862 }1863 }18641865 for (int nxt_idx : neigh_[cur_idx]) {1866 if (!vis[nxt_idx]) {1867 vis[nxt_idx] = true;1868 q.push(nxt_idx);1869 }1870 }1871 }18721873 // Group entire component, checking if value is defined.1874 for (int cur_idx : component) {1875 comp_id[cur_idx] = comp_count;1876 comp[comp_id[cur_idx]].push_back(cur_idx);1877 }18781879 // Defines value if needed.1880 if (value_defined)1881 define_comp(comp_count, new_value);18821883 ++comp_count;1884 }1885 }18861887 // Initial parsing of different restrictions.1888 std::vector<std::set<int>> diff_containing_comp_idx(comp_count);1889 {1890 int dist_id = 0;1891 for (const std::set<int> &diff : diff_restrictions_) {1892 // Checks if there are too many different values.1893 if (static_cast<uint64_t>(diff.size() - 1) +1894 static_cast<uint64_t>(value_l_) >1895 static_cast<uint64_t>(value_r_))1896 throw detail::contradiction_error(1897 "list", "tried to generate " +1898 std::to_string(diff.size()) +1899 " different values, but the maximum is " +1900 std::to_string(value_r_ - value_l_ + 1));19011902 // Checks if two values in same component are marked as1903 // different.1904 std::set<int> comp_ids;1905 for (int idx : diff) {1906 if (comp_ids.count(comp_id[idx]))1907 throw detail::contradiction_error(1908 "list", "tried to set two indices as equal and "1909 "different");1910 comp_ids.insert(comp_id[idx]);19111912 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);1913 }1914 ++dist_id;1915 }1916 }19171918 // If some value is in >= 3 sets, then there is a cycle.1919 for (auto &diff_containing : diff_containing_comp_idx)1920 if (diff_containing.size() >= 3)1921 throw detail::complex_restrictions_error(1922 "list",1923 "one index cannot be in >= 3 'different' restrictions");19241925 std::vector<bool> vis_diff(diff_restrictions_.size(), false);1926 std::vector<bool> initially_defined_comp_idx(comp_count, false);19271928 // Fills the value in a tree defined by "different" restrictions.1929 auto define_tree = [&](int diff_id) {1930 // The set `diff_restrictions_[diff_id]` can have some1931 // values that are defined.19321933 // Generates set of already defined values.1934 std::set<T> defined_values;1935 for (int idx : diff_restrictions_[diff_id])1936 if (defined_idx[idx]) {1937 // Checks if two values in `diff_restrictions_[dist_id]`1938 // have been set to the same value1939 if (defined_values.count(vec[idx]))1940 throw detail::contradiction_error(1941 "list",1942 "tried to set two indices as equal and different");19431944 defined_values.insert(vec[idx]);1945 }19461947 // Generates values in this root "different" restriction.1948 {1949 int new_value_count = diff_restrictions_[diff_id].size() -1950 static_cast<int>(defined_values.size());1951 std::vector<T> generated_values =1952 generate_distinct_values(new_value_count, defined_values);1953 auto val_it = generated_values.begin();1954 for (int idx : diff_restrictions_[diff_id])1955 if (defined_idx[idx]) {1956 // The root can cover these components, but there should1957 // not be any other defined in this tree.1958 initially_defined_comp_idx[comp_id[idx]] = false;1959 } else {1960 define_comp(comp_id[idx], *val_it);1961 ++val_it;1962 }1963 }19641965 // BFS on the tree of "different" restrictions.1966 std::queue<std::pair<int, int>> q; // {id, parent id}1967 q.emplace(diff_id, -1);1968 vis_diff[diff_id] = true;1969 while (!q.empty()) {1970 auto [cur_diff, parent] = q.front();1971 q.pop();19721973 std::set<int> neigh_diff;1974 for (int idx : diff_restrictions_[cur_diff])1975 for (int nxt_diff :1976 diff_containing_comp_idx[comp_id[idx]]) {1977 if (nxt_diff == cur_diff or nxt_diff == parent)1978 continue;19791980 // Cycle found.1981 if (vis_diff[nxt_diff])1982 throw detail::complex_restrictions_error(1983 "list",1984 "cycle found in 'different' restrictions");19851986 neigh_diff.insert(nxt_diff);1987 }19881989 for (int nxt_diff : neigh_diff) {1990 vis_diff[nxt_diff] = true;1991 q.emplace(nxt_diff, cur_diff);19921993 // Generates this "different" restriction.1994 std::set<T> nxt_defined_values;1995 for (int idx2 : diff_restrictions_[nxt_diff])1996 if (defined_idx[idx2]) {1997 // There cannot be any more defined. This case is1998 // when there are values not covered by a single1999 // "different" restriction in the tree.2000 if (initially_defined_comp_idx[comp_id[idx2]])2001 throw detail::complex_restrictions_error(2002 "list");20032004 nxt_defined_values.insert(vec[idx2]);2005 }2006 int new_value_count =2007 diff_restrictions_[nxt_diff].size() -2008 static_cast<int>(nxt_defined_values.size());2009 std::vector<T> generated_values = generate_distinct_values(2010 new_value_count, nxt_defined_values);2011 auto val_it = generated_values.begin();2012 for (int idx2 : diff_restrictions_[nxt_diff])2013 if (!defined_idx[idx2]) {2014 define_comp(comp_id[idx2], *val_it);2015 ++val_it;2016 }2017 }2018 }2019 };20202021 // Loops through "different" restrictions, sorts "different"2022 // restrictions by number of defined components (non-increasing). This2023 // guarantees that if there is a valid root (that covers all 'defined'),2024 // we find it.2025 {2026 std::vector<std::pair<int, int>> defined_cnt_and_diff_idx;2027 int dist_id = 0;2028 for (const std::set<int> &diff : diff_restrictions_) {2029 int defined_cnt = 0;2030 for (int idx : diff)2031 if (defined_idx[idx]) {2032 ++defined_cnt;2033 initially_defined_comp_idx[comp_id[idx]] = true;2034 }2035 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);2036 ++dist_id;2037 }20382039 std::sort(defined_cnt_and_diff_idx.rbegin(),2040 defined_cnt_and_diff_idx.rend());2041 for (auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)2042 if (!vis_diff[diff_idx])2043 define_tree(diff_idx);2044 }20452046 // Loops through "different" restrictions do define the rest.2047 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();2048 ++dist_id)2049 if (!vis_diff[dist_id])2050 define_tree(dist_id);20512052 // Define final values. These values all should be random in [l, r], and2053 // the "different" restrictions have already been processed. However,2054 // there can be still equality restrictions, so we define entire2055 // components.2056 for (int idx = 0; idx < size_; ++idx)2057 if (!defined_idx[idx])2058 define_comp(comp_id[idx], next<T>(value_l_, value_r_));20592060 if (!values_.empty()) {2061 // Needs to fetch the values from the value set.2062 std::vector<T> value_vec(values_.begin(), values_.end());2063 for (T &val : vec)2064 val = value_vec[val];2065 }20662067 return value(vec);2068 }20692070 private:2071 // Materializes neigh_ after the first equality restriction.2072 void ensure_neigh_allocated() const {2073 if (neigh_.size() == static_cast<size_t>(size_))2074 return;2075 neigh_.assign(size_, {});2076 }20772078 // Materializes val_range_ after the first per-index restriction.2079 void ensure_val_range_materialized() const {2080 if (!uses_full_range_)2081 return;2082 val_range_.assign(size_, {value_l_, value_r_});2083 uses_full_range_ = false;2084 }20852086 // Returns the allowed value range at index idx.2087 std::pair<T, T> val_range_at(int idx) const {2088 if (uses_full_range_)2089 return {value_l_, value_r_};2090 return val_range_[idx];2091 }20922093 // Generates a uniformly random list of k distinct values in `[value_l,2094 // value_r]`, such that no value is in `forbidden_values`.2095 std::vector<T>2096 generate_distinct_values(int k, const std::set<T> &forbidden_values) const {2097 for (auto forbidden : forbidden_values)2098 tgen_ensure(value_l_ <= forbidden and forbidden <= value_r_);2099 const T num_available =2100 (value_r_ - value_l_ + 1) - forbidden_values.size();2101 if (num_available < k)2102 throw detail::complex_restrictions_error(2103 "list", "not enough distinct values");2104 if (forbidden_values.empty())2105 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();21062107 std::map<T, T> virtual_list;2108 std::vector<T> gen_list;2109 for (int i = 0; i < k; ++i) {2110 T j = next<T>(i, num_available - 1);2111 T vj = virtual_list.count(j) ? virtual_list[j] : j;2112 T vi = virtual_list.count(i) ? virtual_list[i] : i;21132114 virtual_list[j] = vi, virtual_list[i] = vj;21152116 gen_list.push_back(virtual_list[i]);2117 }21182119 for (T &val : gen_list)2120 val += value_l_;21212122 std::vector<std::pair<T, int>> values_sorted;2123 for (std::size_t i = 0; i < gen_list.size(); ++i)2124 values_sorted.emplace_back(gen_list[i], i);2125 std::sort(values_sorted.begin(), values_sorted.end());2126 auto cur_it = forbidden_values.begin();2127 int smaller_forbidden_count = 0;2128 for (auto [val, idx] : values_sorted) {2129 while (cur_it != forbidden_values.end() and2130 *cur_it <= val + smaller_forbidden_count)2131 ++cur_it, ++smaller_forbidden_count;2132 gen_list[idx] += smaller_forbidden_count;2133 }21342135 return gen_list;2136 }21372138 // If this generator has no constraints beyond [value_l_, value_r_],2139 // returns independent uniform samples; otherwise returns std::nullopt.2140 // O(n).2141 std::optional<value> try_gen_unconstrained() const {2142 if (!values_.empty() or index_constraints_)2143 return std::nullopt;21442145 std::vector<T> vec(size_);2146 for (int i = 0; i < size_; ++i)2147 vec[i] = next<T>(value_l_, value_r_);2148 return value(vec);2149 }21502151 // If this generator is exactly all-distinct in [value_l_, value_r_],2152 // returns a uniformly random list; otherwise returns std::nullopt.2153 // Optimized for performance (distinct_range fast path).2154 // O(n log n).2155 std::optional<value> try_gen_all_different() const {2156 if (!values_.empty() or diff_restrictions_.size() != 1)2157 return std::nullopt;21582159 const std::set<int> &diff = diff_restrictions_[0];2160 if (static_cast<int>(diff.size()) != size_ or *diff.begin() != 0 or2161 *diff.rbegin() != size_ - 1)2162 return std::nullopt;21632164 if (!neigh_.empty()) {2165 for (const auto &adj : neigh_) {2166 if (!adj.empty())2167 return std::nullopt;2168 }2169 }21702171 if (index_constraints_)2172 return std::nullopt;21732174 if (static_cast<long long>(size_) >2175 static_cast<long long>(value_r_) - value_l_ + 1)2176 throw detail::contradiction_error(2177 "list", "tried to generate " + std::to_string(size_) +2178 " different values, but the maximum is " +2179 std::to_string(value_r_ - value_l_ + 1));21802181 return distinct_range<T>(value_l_, value_r_).gen_list(size_);2182 }2183};21842185/*******************2186 * *2187 * PERMUTATION *2188 * *2189 *******************/21902191/*2192 * Permutation generation.2193 *2194 * Permutation are defined always as numbers in [0, n), that is, 0-based.2195 */21962197struct permutation : gen_base<permutation> {2198 int size_; // Size of permutation.2199 std::vector<std::pair<int, int>> defs_; // {idx, value}.2200 std::optional<std::vector<int>> cycle_sizes_; // Cycle sizes.22012202 // Creates generator for permutation of size 'size'.2203 permutation(int size) : size_(size) {2204 tgen_ensure(size_ > 0, "permutation: size must be positive");2205 }22062207 // Restricts permutations for permutation[idx] = val.2208 permutation &fix(int idx, int val) {2209 tgen_ensure(0 <= idx and idx < size_,2210 "permutation: index must be valid");2211 defs_.emplace_back(idx, val);2212 return *this;2213 }22142215 // Restricts permutations for permutation to have cycle sizes.2216 permutation &cycles(const std::vector<int> &cycle_sizes) {2217 tgen_ensure(2218 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),2219 "permutation: cycle sizes must add up to size of permutation");2220 cycle_sizes_ = cycle_sizes;2221 return *this;2222 }2223 permutation &cycles(const std::initializer_list<int> &cycle_sizes) {2224 return cycles(std::vector<int>(cycle_sizes));2225 }22262227 // Permutation value.2228 // Operations on a value are not random.2229 struct value : gen_value_base<value> {2230 using tgen_is_sequential_tag = detail::is_sequential_tag;22312232 using std_type = std::vector<int>; // std type for value.2233 std::vector<int> vec_; // Permutation.2234 char sep_; // Separator for printing.2235 bool add_1_; // If should add 1, for printing.22362237 value(const std::vector<int> &vec)2238 : vec_(vec), sep_(' '), add_1_(false) {2239 tgen_ensure(!vec_.empty(), "permutation: value: cannot be empty");2240 std::vector<bool> vis(vec_.size(), false);2241 for (int i = 0; i < size(); ++i) {2242 tgen_ensure(0 <= vec_[i] and2243 vec_[i] < static_cast<int>(vec_.size()),2244 "permutation: value: values must be from `0` to "2245 "`size-1`");2246 tgen_ensure(!vis[vec_[i]],2247 "permutation: value: cannot have repeated values");2248 vis[vec_[i]] = true;2249 }2250 }2251 value(const std::initializer_list<int> &il)2252 : value(std::vector<int>(il)) {}22532254 // Fetches size.2255 int size() const { return vec_.size(); }22562257 // Fetches position idx.2258 const int &operator[](int idx) const {2259 tgen_ensure(0 <= idx and idx < size(),2260 "permutation: value: index out of bounds");2261 return vec_[idx];2262 }22632264 // Returns parity of the permutation (+1 if even, -1 if odd).2265 // O(n).2266 int parity() const {2267 std::vector<bool> vis(size(), false);2268 int cycles = 0;22692270 for (int i = 0; i < size(); ++i)2271 if (!vis[i]) {2272 ++cycles;2273 for (int j = i; !vis[j]; j = vec_[j])2274 vis[j] = true;2275 }2276 // Even iff (n - cycles) is even.2277 return ((size() - cycles) % 2 == 0) ? +1 : -1;2278 }22792280 // Sorts values in increasing order.2281 // O(n).2282 value &sort() {2283 for (int i = 0; i < size(); ++i)2284 vec_[i] = i;2285 return *this;2286 }22872288 // Reverses permutation.2289 // O(n).2290 value &reverse() {2291 std::reverse(vec_.begin(), vec_.end());2292 return *this;2293 }22942295 // Inverse of the permutation.2296 // O(n).2297 value &inverse() {2298 std::vector<int> inv(size());2299 for (int i = 0; i < size(); ++i)2300 inv[vec_[i]] = i;2301 swap(vec_, inv);2302 return *this;2303 }23042305 // Sets the separator, for printing.2306 // O(1).2307 value &separator(char sep) {2308 sep_ = sep;2309 return *this;2310 }23112312 // Sets that should print values 1-based.2313 // O(1).2314 value &add_1() {2315 add_1_ = true;2316 return *this;2317 }23182319 // Shuffles permutation uniformly.2320 // O(n).2321 value &shuffle() {2322 for (int i = 0; i < size(); ++i)2323 std::swap(vec_[i], vec_[next(0, size() - 1)]);2324 return *this;2325 }23262327 // Returns a random element uniformly.2328 // O(1).2329 int pick() const { return vec_[next<int>(0, size() - 1)]; }23302331 // Returns vec_[i] with probability proportional to distribution[i].2332 // O(1).2333 template <typename Dist>2334 int pick_by_distribution(const std::vector<Dist> &distribution) const {2335 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),2336 "value and distribution must have the same size");2337 return vec_[next_by_distribution(distribution)];2338 }2339 template <typename Dist>2340 int pick_by_distribution(2341 const std::initializer_list<Dist> &distribution) const {2342 return pick_by_distribution(std::vector<Dist>(distribution));2343 }23442345 // Prints to std::ostream, separated by sep_.2346 friend std::ostream &operator<<(std::ostream &out, const value &val) {2347 for (int i = 0; i < val.size(); ++i) {2348 if (i > 0)2349 out << val.sep_;2350 out << val[i] + val.add_1_;2351 }2352 return out;2353 }23542355 // Gets a std::vector representing the value.2356 std::vector<int> to_std() const { return std_type(vec_); }2357 };23582359 // Generates permutation value.2360 // O(n).2361 value gen() const {2362 if (!cycle_sizes_) {2363 // Cycle sizes not specified.2364 std::vector<int> idx_to_val(size_, -1), val_to_idx(size_, -1);2365 for (auto [idx, val] : defs_) {2366 tgen_ensure(2367 0 <= val and val < size_,2368 "permutation: value in permutation must be in [0, " +2369 std::to_string(size_) + ")");23702371 if (idx_to_val[idx] != -1) {2372 tgen_ensure(idx_to_val[idx] == val,2373 "permutation: cannot set an index to two "2374 "different values");2375 } else2376 idx_to_val[idx] = val;23772378 if (val_to_idx[val] != -1) {2379 tgen_ensure(val_to_idx[val] == idx,2380 "permutation: cannot set two indices to the "2381 "same value");2382 } else2383 val_to_idx[val] = idx;2384 }23852386 std::vector<int> perm(size_);2387 std::iota(perm.begin(), perm.end(), 0);2388 shuffle(perm.begin(), perm.end());2389 int cur_idx = 0;2390 for (int &i : idx_to_val)2391 if (i == -1) {2392 // While this value is used, skip.2393 while (val_to_idx[perm[cur_idx]] != -1)2394 ++cur_idx;2395 i = perm[cur_idx++];2396 }2397 return idx_to_val;2398 }23992400 // Creates cycles.2401 std::vector<int> order(size_);2402 std::iota(order.begin(), order.end(), 0);2403 shuffle(order.begin(), order.end());2404 int idx = 0;2405 std::vector<std::vector<int>> cycles;2406 for (int cycle_size : *cycle_sizes_) {2407 cycles.emplace_back();2408 for (int i = 0; i < cycle_size; ++i)2409 cycles.back().push_back(order[idx++]);2410 }24112412 // Retrieves permutation from cycles.2413 std::vector<int> perm(size_, -1);2414 for (const std::vector<int> &cycle : cycles) {2415 int cur_size = cycle.size();2416 for (int i = 0; i < cur_size; ++i)2417 perm[cycle[i]] = cycle[(i + 1) % cur_size];2418 }24192420 return value(perm);2421 }2422};24232424/************2425 * *2426 * MATH *2427 * *2428 ************/24292430namespace math {24312432namespace detail {24332434using namespace tgen::detail;24352436inline int popcount(uint64_t x) { return __builtin_popcountll(x); }24372438inline int ctzll(uint64_t x) {2439 // Mystery code found on the internet.2440 // Uses de Bruijn sequence.2441 static const unsigned char index64[64] = {2442 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,2443 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,2444 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,2445 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};2446 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];2447}24482449inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {2450 return static_cast<u128>(a) * b % m;2451}24522453// O(log n).2454// 0 <= x < m.2455inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {2456 if (!y)2457 return 1;2458 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);2459 return y % 2 ? mul_mod(x, ans, m) : ans;2460}24612462} // namespace detail24632464// O(log^2 n).2465inline bool is_prime(uint64_t n) {2466 if (n < 2)2467 return false;2468 if (n == 2 or n == 3)2469 return true;2470 if (n % 2 == 0)2471 return false;24722473 uint64_t r = detail::ctzll(n - 1), d = n >> r;2474 // These bases are guaranteed to work for n <= 2^64.2475 for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {2476 uint64_t x = detail::expo_mod(a, d, n);2477 if (x == 1 or x == n - 1 or a % n == 0)2478 continue;24792480 for (uint64_t j = 0; j < r - 1; ++j) {2481 x = detail::mul_mod(x, x, n);2482 if (x == n - 1)2483 break;2484 }2485 if (x != n - 1)2486 return false;2487 }2488 return true;2489}24902491namespace detail {24922493inline uint64_t pollard_rho(uint64_t n) {2494 if (n == 1 or is_prime(n))2495 return n;2496 auto f = [n](uint64_t x) { return mul_mod(x, x, n) + 1; };24972498 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;2499 while (t % 40 != 0 or std::gcd(prd, n) == 1) {2500 if (x == y)2501 x = ++x0, y = f(x);2502 q = mul_mod(prd, x > y ? x - y : y - x, n);2503 if (q != 0)2504 prd = q;2505 x = f(x), y = f(f(y)), ++t;2506 }2507 return std::gcd(prd, n);2508}25092510inline std::vector<uint64_t> factor(uint64_t n) {2511 if (n == 1)2512 return {};2513 if (is_prime(n))2514 return {n};2515 uint64_t d = pollard_rho(n);2516 std::vector<uint64_t> l = factor(d), r = factor(n / d);2517 l.insert(l.end(), r.begin(), r.end());2518 return l;2519}25202521// Error handling.2522template <typename T>2523std::runtime_error there_is_no_in_range_error(const std::string &type, T l,2524 T r) {2525 return error("math: there is no " + type + " in range [" +2526 std::to_string(l) + ", " + std::to_string(r) + "]");2527}2528template <typename T>2529std::runtime_error there_is_no_from_error(const std::string &type, T r) {2530 return error("math: there is no " + type + " from " + std::to_string(r));2531}2532template <typename T>2533std::runtime_error there_is_no_upto_error(const std::string &type, T r) {2534 return error("math: there is no " + type + " up to " + std::to_string(r));2535}25362537// O(log mod).2538// 0 < a < mod.2539// gcd(a, mod) = 1.2540inline i128 modular_inverse_128(i128 a, i128 mod) {2541 tgen_ensure(0 < a and a < mod,2542 "math: modular inverse requires 0 < value < mod");25432544 i128 t = 0, new_t = 1;2545 i128 r = mod, new_r = a;25462547 while (new_r != 0) {2548 i128 q = r / new_r;25492550 auto tmp_t = t - q * new_t;2551 t = new_t;2552 new_t = tmp_t;25532554 auto tmp_r = r - q * new_r;2555 r = new_r;2556 new_r = tmp_r;2557 }25582559 tgen_ensure(r == 1, "math: remainder and mod must be coprime");25602561 if (t < 0)2562 t += mod;2563 return t;2564}25652566// checks if a * b <= limit, for positive numbers.2567inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {2568 if (a == 0 or b == 0)2569 return true;2570 return a <= limit / b;2571}25722573// base^exp, or null if base^exp > limit.2574inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,2575 uint64_t limit) {2576 uint64_t result = 1;25772578 while (exp) {2579 if (exp & 1) {2580 if (!mul_leq(result, base, limit))2581 return std::nullopt;2582 result *= base;2583 }25842585 exp >>= 1;2586 // Necessary for correctness.2587 if (!exp)2588 break;25892590 if (!mul_leq(base, base, limit))2591 return std::nullopt;2592 base *= base;2593 }2594 return result;2595}25962597// O(log n log k).2598// 0 < k.2599inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {2600 tgen_ensure_against_bug(k > 0, "math: value must be valid");2601 if (k == 1 or n <= 1)2602 return n;26032604 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);26052606 while (lo < hi) {2607 uint64_t mid = lo + (hi - lo + 1) / 2;26082609 if (expo(mid, k, n)) {2610 lo = mid;2611 } else {2612 hi = mid - 1;2613 }2614 }2615 return lo;2616}26172618// gcd(a, b).2619// O(log a).2620inline i128 gcd128(i128 a, i128 b) {2621 if (a < 0)2622 a = -a;2623 if (b < 0)2624 b = -b;2625 while (b != 0) {2626 i128 t = a % b;2627 a = b;2628 b = t;2629 }2630 return a;2631}26322633// min(2^64, a*b).2634// O(log a).2635// a, b >= 0.2636inline i128 mul_saturate(i128 a, i128 b) {2637 tgen_ensure(a >= 0 and b >= 0);2638 static const i128 LIMIT = static_cast<i128>(1) << 64;2639 if (a == 0 or b == 0)2640 return 0;2641 if (a > LIMIT / b)2642 return LIMIT;2643 return a * b;2644}26452646struct crt {2647 using T = i128;2648 T a, m;26492650 crt() : a(0), m(1) {}2651 crt(T a_, T m_) : a(a_), m(m_) {}2652 crt operator*(crt C) {2653 if (m == 0 or C.m == 0)2654 return {-1, 0};26552656 T g = gcd128(m, C.m);2657 if ((C.a - a) % g != 0)2658 return {-1, 0};26592660 T m1 = m / g;2661 T m2 = C.m / g;26622663 if (m2 == 1)2664 return {a, m};26652666 T inv = modular_inverse_128(m1 % m2, m2);26672668 T k = ((C.a - a) / g) % m2;2669 if (k < 0)2670 k += m2;26712672 k = static_cast<u128>(k) * inv % m2;26732674 T lcm = mul_saturate(m, m2);26752676 T res = (a + static_cast<T>((static_cast<u128>(k) * m) % lcm)) % lcm;2677 if (res < 0)2678 res += lcm;26792680 return {res, lcm};2681 }2682};26832684// Math hacks to operate on log space.26852686inline constexpr long double LOG_ZERO = -INFINITY;2687inline constexpr long double LOG_ONE = 0.0;26882689inline long double log_space(long double x) {2690 return x == 0.0 ? LOG_ZERO : std::log(x);2691}26922693// Math hack to add two values in log space.2694inline long double add_log_space(long double a, long double b) {2695 if (a < b)2696 std::swap(a, b);2697 if (b == LOG_ZERO)2698 return a;2699 return a + log1p(exp(b - a));2700}27012702// Math hack to subtract two values in log space.2703// a >= b.2704inline long double sub_log_space(long double a, long double b) {2705 if (b >= a)2706 return LOG_ZERO;2707 if (b == LOG_ZERO)2708 return a;2709 return a + log1p(-exp(b - a));2710}27112712} // namespace detail27132714// Sorted.2715// O(n^(1/4) log n) expected.2716// 0 < n.2717inline std::vector<uint64_t> factor(uint64_t n) {2718 tgen_ensure(n > 0, "math: number to factor must be positive");2719 auto factors = detail::factor(n);2720 std::sort(factors.begin(), factors.end());2721 return factors;2722}27232724// Sorted.2725// O(n^(1/4) log n) expected.2726// 0 < n.2727inline std::vector<std::pair<uint64_t, int>> factor_by_prime(uint64_t n) {2728 tgen_ensure(n > 0, "math: number to factor must be positive");2729 std::vector<std::pair<uint64_t, int>> primes;2730 for (uint64_t p : factor(n)) {2731 if (!primes.empty() and primes.back().first == p)2732 ++primes.back().second;2733 else2734 primes.emplace_back(p, 1);2735 }2736 return primes;2737}27382739// O(log mod).2740// 0 < a < mod.2741// gcd(a, mod) = 1.2742inline uint64_t modular_inverse(uint64_t a, uint64_t mod) {2743 return detail::modular_inverse_128(a, mod);2744}27452746// O(n^(1/4) log n) expected.2747// 0 < n.2748inline uint64_t totient(uint64_t n) {2749 tgen_ensure(n > 0, "math: totient(0) is undefined");2750 uint64_t phi = n;27512752 for (auto [p, e] : factor_by_prime(n))2753 phi -= phi / p;27542755 return phi;2756}27572758// Returns `(p_i, g_i)`: `p_i` is the prime, `g_i` is the gap.2759inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &2760prime_gaps() {2761 // From https://en.wikipedia.org/wiki/Prime_gap.2762 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{2763 /* clang-format off */ {2764 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,2765 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,2766 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,2767 191912783, 387096133, 436273009, 1294268491, 1453168141,2768 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,2769 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,2770 241160624143, 297501075799, 303371455241, 304599508537,2771 416608695821, 461690510011, 614487453523, 738832927927,2772 1346294310749, 1408695493609, 1968188556461, 2614941710599,2773 7177162611713, 13829048559701, 19581334192423, 42842283925351,2774 90874329411493, 171231342420521, 218209405436543, 1189459969825483,2775 1686994940955803, 1693182318746371, 43841547845541059,2776 55350776431903243, 80873624627234849, 203986478517455989,2777 218034721194214273, 305405826521087869, 352521223451364323,2778 401429925999153707, 418032645936712127, 804212830686677669,2779 1425172824437699411, 5733241593241196731, 67879889996577777972780 }, /* clang-format on */2781 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,2782 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,2783 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,2784 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,2785 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,2786 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,2787 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};27882789 return value;2790}27912792// Returns pair (first_composite_in_gap, last_composite_in_gap).2793// O(log(right)) approximately.2794inline std::pair<uint64_t, uint64_t> prime_gap_upto(uint64_t right) {2795 if (right < 4)2796 throw detail::there_is_no_upto_error("prime gap", right);27972798 const auto &[P, G] = prime_gaps();2799 for (int i = P.size() - 1;; --i) {2800 if (P[i] >= right)2801 continue;28022803 uint64_t real_right = std::min(right, P[i] + G[i] - 1);2804 uint64_t prev = i > 0 ? G[i - 1] : 0;2805 uint64_t curr = real_right - P[i];28062807 if (curr >= prev)2808 return {P[i] + 1, real_right};2809 }2810}28112812// From https://oeis.org/A002182/b002182.txt.2813inline const std::vector<uint64_t> &highly_composites() {2814 /* clang-format off */2815 static const std::vector<uint64_t> highly_composites = {2816 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,2817 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,2818 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,2819 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,2820 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,2821 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,2822 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,2823 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,2824 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,2825 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,2826 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,2827 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,2828 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,2829 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,2830 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,2831 26985313555200, 27949074753600, 32607253879200, 46581791256000,2832 48910880818800, 55898149507200, 65214507758400, 93163582512000,2833 97821761637600, 130429015516800, 195643523275200, 260858031033600,2834 288807105787200, 391287046550400, 577614211574400, 782574093100800,2835 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,2836 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,2837 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,2838 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,2839 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,2840 72779390658374400, 74801040398884800, 106858629141264000,2841 112201560598327200, 149602080797769600, 224403121196654400,2842 299204161595539200, 374005201994424000, 448806242393308800,2843 673209363589963200, 748010403988848000, 897612484786617600,2844 1122015605983272000, 1346418727179926400, 1795224969573235200,2845 2244031211966544000, 2692837454359852800, 3066842656354276800,2846 4381203794791824000, 4488062423933088000, 6133685312708553600,2847 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,2848 15334213281771384000ULL, 18401055938125660800ULL}; /* clang-format on */2849 return highly_composites;2850}28512852// O(log(right)) approximately.2853inline uint64_t highly_composite_upto(uint64_t right) {2854 for (int i = highly_composites().size() - 1; i >= 0; --i)2855 if (highly_composites()[i] <= right)2856 return highly_composites()[i];28572858 throw detail::there_is_no_upto_error("highly composite number", right);2859}28602861// O(log^3 (right)) expected.2862// Generates a random prime in [left, right].2863inline uint64_t gen_prime(uint64_t left, uint64_t right) {2864 if (right < left or right < 2)2865 throw detail::there_is_no_in_range_error("prime", left, right);2866 left = std::max<uint64_t>(left, 2);2867 auto [l_gap, r_gap] = prime_gap_upto(right);2868 if (right - left + 1 <= r_gap - l_gap + 1) {2869 // There might be no primes in the range.2870 std::vector<uint64_t> vals(right - left + 1);2871 iota(vals.begin(), vals.end(), left);2872 shuffle(vals.begin(), vals.end());2873 for (uint64_t i : vals)2874 if (is_prime(i))2875 return i;2876 throw detail::there_is_no_in_range_error("prime", left, right);2877 }28782879 uint64_t n;2880 do {2881 n = next(left, right);2882 } while (!is_prime(n));2883 return n;2884}28852886// O(log^3 (left)) expected.2887// left <= 2^64 - 59.2888inline uint64_t prime_from(uint64_t left) {2889 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,2890 "math: invalid bound");2891 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)2892 if (is_prime(i))2893 return i;2894}28952896// O(log^3 (right)) expected.2897inline uint64_t prime_upto(uint64_t right) {2898 if (right >= 2)2899 for (uint64_t i = right; i >= 2; --i)2900 if (is_prime(i))2901 return i;2902 throw detail::there_is_no_upto_error("prime", right);2903}29042905// O(n^(1/4) log n) expected.2906// 0 < n.2907inline int num_divisors(uint64_t n) {2908 int divisors = 1;2909 for (auto [p, e] : factor_by_prime(n))2910 divisors *= (e + 1);2911 return divisors;2912}29132914// Random number in [left, right] with `divisor_count` divisors.2915// O(log(right) log(divisor_count)).2916// divisor_count must be prime.2917inline uint64_t gen_divisor_count(uint64_t left, uint64_t right,2918 int divisor_count) {2919 tgen_ensure(divisor_count > 0 and is_prime(divisor_count),2920 "math: divisor count must be prime");2921 int root = divisor_count - 1;2922 uint64_t p = gen_prime(detail::kth_root_floor(left, root),2923 detail::kth_root_floor(right, root));2924 return *detail::expo(p, root, right);2925}29262927// O(|mods| + log (right)).2928// |rems| = |mods|.2929// rems_i < mods_i.2930inline uint64_t gen_congruent(uint64_t left, uint64_t right,2931 std::vector<uint64_t> rems,2932 std::vector<uint64_t> mods) {2933 if (left > right)2934 throw detail::there_is_no_in_range_error("congruent number", left,2935 right);2936 tgen_ensure(rems.size() == mods.size(),2937 "math: number of remainders and mods must be the same");2938 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");29392940 detail::crt crt;2941 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {2942 tgen_ensure(rems[i] < mods[i],2943 "math: remainder must be smaller than the mod");2944 crt = crt * detail::crt(rems[i], mods[i]);29452946 if (crt.a == -1)2947 throw detail::there_is_no_in_range_error("congruent number", left,2948 right);2949 if (crt.m > right) {2950 if (!(left <= crt.a and crt.a <= right))2951 throw detail::there_is_no_in_range_error("congruent number",2952 left, right);29532954 for (int j = 0; j < static_cast<int>(rems.size()); ++j)2955 if (crt.a % mods[j] != rems[j])2956 throw detail::there_is_no_in_range_error("congruent number",2957 left, right);2958 return crt.a;2959 }2960 }29612962 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;2963 uint64_t k_max = (right - crt.a) / crt.m;29642965 if (k_min > k_max)2966 throw detail::there_is_no_in_range_error("congruent number", left,2967 right);29682969 return crt.a + next(k_min, k_max) * crt.m;2970}29712972// O(log (right)).2973// rem < mod.2974inline uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem,2975 uint64_t mod) {2976 return gen_congruent(left, right, std::vector<uint64_t>({rem}),2977 std::vector<uint64_t>({mod}));2978}29792980// First congruent number >= left.2981// O(|mods| + log (left)).2982// |rems| = |mods|.2983// rems_i < mods_i.2984inline uint64_t congruent_from(uint64_t left, std::vector<uint64_t> rems,2985 std::vector<uint64_t> mods) {2986 tgen_ensure(rems.size() == mods.size(),2987 "math: number of remainders and mods must be the same");2988 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");29892990 detail::crt crt;2991 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {2992 tgen_ensure(rems[i] < mods[i],2993 "math: remainder must be smaller than the mod");2994 crt = crt * detail::crt(rems[i], mods[i]);29952996 if (crt.a == -1)2997 throw detail::there_is_no_from_error("congruent number", left);2998 if (crt.m > std::numeric_limits<uint64_t>::max()) {2999 if (crt.a < left)3000 throw detail::error(3001 "math: congruent number does not exist or is too large");30023003 for (int j = 0; j < static_cast<int>(rems.size()); ++j)3004 if (crt.a % mods[j] != rems[j])3005 throw detail::error("math: congruent number does "3006 "not exist or is too large");3007 return crt.a;3008 }3009 }30103011 uint64_t k = 0;3012 if (crt.a < left)3013 k = ((left - crt.a) + crt.m - 1) / crt.m;3014 detail::i128 result = crt.a + k * crt.m;30153016 if (result > std::numeric_limits<uint64_t>::max())3017 throw detail::error("math: congruent number is too large");3018 return result;3019}30203021// O(log (left))3022// rem < mod.3023inline uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod) {3024 return congruent_from(left, std::vector<uint64_t>{rem},3025 std::vector<uint64_t>{mod});3026}30273028// Last congruent number <= right.3029// O(|mods| + log (right)).3030// |rems| = |mods|.3031// rems_i < mods_i.3032inline uint64_t congruent_upto(uint64_t right, std::vector<uint64_t> rems,3033 std::vector<uint64_t> mods) {3034 tgen_ensure(rems.size() == mods.size(),3035 "math: number of remainders and mods must be the same");3036 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");30373038 detail::crt crt;3039 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {3040 tgen_ensure(rems[i] < mods[i],3041 "math: remainder must be smaller than the mod");30423043 crt = crt * detail::crt(rems[i], mods[i]);30443045 if (crt.a == -1)3046 throw detail::there_is_no_upto_error("congruent number", right);3047 if (crt.m > right) {3048 if (!(crt.a <= right))3049 throw detail::there_is_no_upto_error("congruent number", right);30503051 for (int j = 0; j < static_cast<int>(rems.size()); ++j)3052 if (crt.a % mods[j] != rems[j])3053 throw detail::there_is_no_upto_error("congruent number",3054 right);3055 return crt.a;3056 }3057 }30583059 if (crt.a > right)3060 throw detail::there_is_no_upto_error("congruent number", right);30613062 uint64_t k = (right - crt.a) / crt.m;3063 detail::i128 result = crt.a + k * crt.m;30643065 if (result < 0)3066 throw detail::there_is_no_upto_error("congruent number", right);3067 return result;3068}30693070// O(log r)3071// rem < mod.3072inline uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod) {3073 return congruent_upto(right, std::vector<uint64_t>{rem},3074 std::vector<uint64_t>{mod});3075}30763077// Mod used for FFT/NTT.3078inline constexpr int FFT_MOD = 998244353;30793080// Fibonacci sequence up to 2^64.3081inline const std::vector<uint64_t> &fibonacci() {3082 static const std::vector<uint64_t> fib = [] {3083 std::vector<uint64_t> v = {0, 1};3084 while (v.back() <=3085 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])3086 v.push_back(v.back() + v[v.size() - 2]);3087 return v;3088 }();3089 return fib;3090}30913092// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).3093// O(n).3094// 0 < n.3095// 0 < part_left.3096inline std::vector<int>3097gen_partition(int n, int part_left = 1,3098 std::optional<int> part_right = std::nullopt) {3099 if (!part_right.has_value())3100 part_right = n;3101 part_right = std::min(*part_right, n);3102 tgen_ensure(n > 0 and part_left > 0,3103 "math: invalid parameters to gen_partition");3104 tgen_ensure(part_left <= n and *part_right > 0, "math: no such partition");31053106 // dp[i] = log(number of ways to add to i).3107 std::vector<long double> dp(n + 1, detail::LOG_ZERO);3108 dp[0] = detail::LOG_ONE;3109 long double window = detail::LOG_ZERO;3110 for (int i = 1; i <= n; ++i) {3111 if (i >= part_left)3112 window = detail::add_log_space(window, dp[i - part_left]);3113 if (i >= *part_right + 1)3114 window = detail::sub_log_space(window, dp[i - *part_right - 1]);3115 dp[i] = window;3116 }3117 tgen_ensure(dp[n] >= 0, "math: no such partition");31183119 // Crazy math tricks ahead.3120 auto dp_pref = dp;3121 for (int i = 1; i <= n; ++i)3122 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);31233124 std::vector<int> part;3125 int sum = n;3126 while (sum > 0) {3127 // Will generate a number such that what remains is in [l, r].3128 int l = std::max(0, sum - *part_right), r = sum - part_left;3129 detail::tgen_ensure_against_bug(r >= 0, "math: r < 0 in gen_partition");31303131 int nxt_sum = std::min(sum, r);3132 long double random = next<long double>(0, 1);31333134 // We generate a value X (log space), and then choose nxt_sum such3135 // that dp_pref[nxt_sum-1] < X <= dp_pref[nxt_sum].31363137 // Math hack:3138 // Let A = pref[l-1], B = pref[r], U = rand().3139 // X = log[exp(A) + U * (exp(B) - exp(A))]3140 // = log{exp(B) * [exp(A) / exp(B) + U * (1 - exp(A) / exp(B))]}3141 // = B + log[exp(A - B) + U - U * exp(A - B))]3142 // = B + log[U + (1 - U) * exp(A - B)].3143 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,3144 val_r = dp_pref[r];3145 while (nxt_sum > l and3146 dp_pref[nxt_sum - 1] >=3147 val_r + detail::log_space(random +3148 (1 - random) * exp(val_l - val_r)))3149 --nxt_sum;31503151 part.push_back(sum - nxt_sum);3152 sum = nxt_sum;3153 }31543155 return part;3156}31573158// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).3159// O(n) time/memory if part_right is not set, O(n * k) time/memory otherwise.3160// 0 < k <= n.3161// 0 <= part_left.3162inline std::vector<int>3163gen_partition_fixed_size(int n, int k, int part_left = 0,3164 std::optional<int> part_right = std::nullopt) {3165 if (!part_right.has_value())3166 part_right = n;3167 part_right = std::min(*part_right, n);3168 tgen_ensure(0 < k and k <= n and part_left >= 0,3169 "math: invalid parameters to gen_partition_fixed_size");3170 tgen_ensure(static_cast<long long>(k) * part_left <= n and3171 n <= static_cast<long long>(k) * (*part_right),3172 "math: no such partition");31733174 // What we need to distribute to the parts.3175 int s = n - k * part_left;31763177 std::vector<int> part(k);3178 if (*part_right == n) {3179 // Stars and bars - O(n).3180 std::vector<int> cuts = {-1};31813182 int total = s + k - 1, bars = k - 1;3183 for (int i = 0; i < total and bars > 0; ++i)3184 if (next<long double>(0, 1) <3185 static_cast<long double>(bars) / (total - i)) {3186 cuts.push_back(i);3187 --bars;3188 }3189 cuts.push_back(total);31903191 // Recovers parts.3192 for (int i = 0; i < k; ++i)3193 part[i] = cuts[i + 1] - cuts[i] - 1;3194 } else {3195 // DP with log trick - O(nk).3196 int u = *part_right - part_left;31973198 // dp[i][j] = log(#ways to fill i parts with sum j)3199 std::vector<std::vector<long double>> dp(3200 k + 1, std::vector<long double>(s + 1, detail::LOG_ZERO));3201 dp[0][0] = detail::LOG_ONE;32023203 for (int i = 1; i <= k; ++i) {3204 std::vector<long double> pref = dp[i - 1];3205 for (int j = 1; j <= s; ++j)3206 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);32073208 for (int j = 0; j <= s; ++j) {3209 dp[i][j] = pref[j];3210 if (j >= u + 1)3211 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);3212 }3213 }32143215 // Recovers parts backwards.3216 int left_to_distribute = s;3217 for (int i = k; i >= 1; --i) {3218 long double log_total = detail::LOG_ZERO;3219 for (int j = 0; j <= u and j <= left_to_distribute; ++j)3220 log_total = detail::add_log_space(3221 log_total, dp[i - 1][left_to_distribute - j]);3222 detail::tgen_ensure_against_bug(3223 log_total != detail::LOG_ZERO,3224 "math: total == 0 in gen_partition_fixed_size");32253226 // Now we choose a number with probability proportional to3227 // dp[i-1][.].32283229 // log(rand() * total) = log(rand()) + log(total).3230 long double random =3231 detail::log_space(next<long double>(0, 1)) + log_total;32323233 long double cur_prob = detail::LOG_ZERO;3234 int chosen = 0;3235 for (int j = 0; j <= u and j <= left_to_distribute; ++j) {3236 cur_prob = detail::add_log_space(3237 cur_prob, dp[i - 1][left_to_distribute - j]);3238 if (random < cur_prob) {3239 chosen = j;3240 break;3241 }3242 }32433244 part[k - i] = chosen;3245 left_to_distribute -= chosen;3246 }3247 }32483249 for (int &i : part)3250 i += part_left;3251 return part;3252}32533254// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).3255// Inspired by jngen rndm.partition: random delimiters, sort, gap recovery;3256// omits jngen's part reordering, shuffles, and two-pass redistribution.3257// 0 < k <= n.3258// 0 <= part_left.3259// Not uniformly random; optimized for speed.3260// O(k log k).3261inline std::vector<uint64_t> gen_partition_fixed_size_fast(3262 uint64_t n, int k, uint64_t part_left = 0,3263 std::optional<uint64_t> part_right = std::nullopt) {3264 if (!part_right.has_value())3265 part_right = n;3266 part_right = std::min(*part_right, n);32673268 detail::u128 n128 = n;3269 detail::u128 k128 = k;3270 detail::u128 part_left128 = part_left;3271 detail::u128 part_right128 = *part_right;32723273 tgen_ensure(k > 0 and k128 <= n128,3274 "math: invalid parameters to gen_partition_fixed_size_fast");3275 tgen_ensure(part_right128 >= part_left128 and3276 k128 * part_left128 <= n128 and3277 k128 * part_right128 >= n128,3278 "math: no such partition");32793280 uint64_t slack_total = n128 - k128 * part_left128;3281 uint64_t slack_max = part_right128 - part_left128;32823283 std::vector<uint64_t> part(k);3284 if (k == 1) {3285 part[0] = slack_total;3286 } else {3287 std::vector<uint64_t> cuts(k - 1);3288 for (uint64_t &d : cuts)3289 d = next<uint64_t>(0, slack_total);3290 std::sort(cuts.begin(), cuts.end());32913292 uint64_t prev = 0;3293 for (int i = 0; i + 1 < k; ++i) {3294 part[i] = cuts[i] - prev;3295 prev = cuts[i];3296 }3297 part[k - 1] = slack_total - prev;3298 }32993300 auto add_part_left = [part_left](uint64_t x) -> uint64_t {3301 detail::u128 val = x + part_left;3302 detail::tgen_ensure_against_bug(3303 val <= std::numeric_limits<uint64_t>::max(),3304 "math: part + part_left exceeds uint64_t in "3305 "gen_partition_fixed_size_fast");3306 return val;3307 };33083309 if (slack_max >= slack_total) {3310 for (uint64_t &x : part)3311 x = add_part_left(x);3312 return part;3313 }33143315 detail::u128 remaining = 0;3316 for (uint64_t &x : part) {3317 if (x > slack_max) {3318 remaining += x - slack_max;3319 x = slack_max;3320 }3321 x = add_part_left(x);3322 }33233324 if (remaining > 0) {3325 for (uint64_t &x : part) {3326 if (x < *part_right && remaining > 0) {3327 detail::u128 room = *part_right - x;3328 detail::u128 add = std::min(remaining, room);3329 detail::u128 val = x + add;3330 detail::tgen_ensure_against_bug(3331 val <= *part_right,3332 "math: part exceeds part_right after redistribution in "3333 "gen_partition_fixed_size_fast");3334 x = val;3335 remaining -= add;3336 }3337 }3338 detail::tgen_ensure_against_bug(3339 remaining == 0, "math: remaining mass after redistribution in "3340 "gen_partition_fixed_size_fast");3341 }33423343 return part;3344}33453346// Random partition of elements into k ordered groups (input order preserved).3347// If max_size is unset, part sizes are uniform via gen_partition_fixed_size.3348// If max_size is set, uses gen_partition_fixed_size_fast (not uniform).3349// O(n) if max_size is unset; O(n + k log k) if max_size is set.3350template <typename T>3351std::vector<std::vector<T>>3352partition_elements(std::vector<T> elements, int k, int min_size = 0,3353 std::optional<uint64_t> max_size = std::nullopt) {3354 size_t n = elements.size();3355 tgen_ensure(k > 0, "math: partition_elements: k must be positive");3356 tgen_ensure(min_size >= 0,3357 "math: partition_elements: min_size must be non-negative");33583359 std::vector<uint64_t> sizes;3360 if (max_size.has_value()) {3361 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);3362 } else {3363 for (int sz : gen_partition_fixed_size(n, k, min_size))3364 sizes.push_back(sz);3365 }33663367 std::vector<std::vector<T>> groups;3368 groups.reserve(k);3369 size_t pos = 0;3370 for (uint64_t sz : sizes) {3371 groups.emplace_back(elements.begin() + pos,3372 elements.begin() + pos + sz);3373 pos += sz;3374 }3375 return groups;3376}33773378}; // namespace math33793380/**************3381 * *3382 * STRING *3383 * *3384 **************/33853386namespace detail {33873388/*3389 * Regex.3390 *3391 * Compatible with testlib's regex.3392 *3393 * Operations:3394 * - A single character yields itself ("a", "3").3395 * - A list of characters inside square braces yields any a random element3396 * from the list ("[abc123]").3397 * - A range of characters is equivalent to listing them ("[a-z1-9A-Z]").3398 * - A pattern followed by {n} yields the pattern repeated n times ("a{3}").3399 * - A pattern followed by {l,r} yields the pattern repeated between l and r3400 * times, uniformly at random ("a{3,5}").3401 * - A list of patterns separated by | yields a random pattern from the3402 * list, uniformly at random ("abc|def|ghi").3403 * - Parentheses can be used for grouping ("a((a|b){3})").3404 *3405 * Examples:3406 * 1. str("[1-9][0-9]{1,2}") generates two- or three-digit numbers.3407 * 2. str("a[b-d]{2}|e") generates "e" or a random string of length 3, with3408 * the first character being 'a' and the second and3409 * third characters being 'b', 'c', or 'd'.3410 * 3. str("[1-9][0-9]{%d}", n-1) generates n-digit numbers.3411 *3412 * Operations defined by {n} and {l,r} are applied from left to right, and3413 * the pattern that comes before has its delimiters defined either by () or3414 * [] at its end or is taken from the beginning of the pattern (in3415 * "a[bc]{2}", "{2}" is applied to "[bc]", and in "[01]abc{3}", the "{3}" is3416 * applied to "[01]abc").3417 */34183419// If it has children, it is either a SEQ or an OR group, defined by the3420// pattern_ field.3421struct regex_node {3422 // Considered to be repetition of left_bound != -1, pattern if3423 // children_.empty(), otherwise "SEQ" or "OR", defined by the pattern_3424 // field.3425 std::string3426 pattern_; // Either pattern, or "SEQ" or "OR" (if !children_.empty()).3427 std::vector<regex_node> children_; // Children, when SEQ or OR.3428 int left_bound_, right_bound_; // Left and right bounds of the repetition,3429 // or -1 if not a repetition.3430 double3431 log_space_num_ways_; // Log space number of ways to match the pattern.3432 std::optional<distinct_container<char>>3433 distinct_; // Distinct generator for the pattern, for [chars].34343435 // c or [chars].3436 regex_node(const std::string &pattern)3437 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {3438 if (pattern.size() == 1) {3439 log_space_num_ways_ = math::detail::LOG_ONE;3440 return;3441 }3442 tgen_ensure_against_bug(pattern[0] == '[' and pattern.back() == ']',3443 "str: invalid regex: expected character class");3444 int size = pattern.size() - 2;3445 log_space_num_ways_ = math::detail::log_space(size);3446 distinct_ = distinct_container<char>(pattern.substr(1, size));3447 }3448 // SEQ or OR.3449 regex_node(const std::string &pattern, std::vector<regex_node> &children)3450 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {3451 if (pattern == "SEQ") {3452 // Multiply the number of ways.3453 log_space_num_ways_ = math::detail::LOG_ONE;3454 for (const auto &child : children)3455 log_space_num_ways_ += child.log_space_num_ways_;3456 } else if (pattern == "OR") {3457 // Add the number of ways.3458 log_space_num_ways_ = math::detail::LOG_ZERO;3459 for (const auto &child : children)3460 log_space_num_ways_ = math::detail::add_log_space(3461 log_space_num_ways_, child.log_space_num_ways_);3462 } else3463 tgen_ensure_against_bug("str: invalid regex: expected SEQ or OR");34643465 children_ = std::move(children);3466 children.clear();3467 }3468 // REP.3469 regex_node(int left_bound, int right_bound, regex_node &child)3470 : pattern_("REP"), left_bound_(left_bound), right_bound_(right_bound) {3471 log_space_num_ways_ = math::detail::LOG_ZERO;3472 for (int i = left_bound; i <= right_bound; ++i)3473 log_space_num_ways_ = math::detail::add_log_space(3474 log_space_num_ways_, i * child.log_space_num_ways_);34753476 children_.push_back(std::move(child));3477 }3478};34793480// State of the regex parser.3481struct regex_state {3482 std::vector<regex_node> cur; // Current sequence of nodes.3483 std::vector<regex_node> branches; // Branches of the current OR group.3484};34853486// Creates a SEQ node from the current state.3487inline regex_node make_regex_seq(regex_state &st) {3488 return regex_node("SEQ", st.cur);3489}34903491// Finishes current state.3492inline regex_node finish_regex_state(regex_state &st) {3493 // SEQ.3494 if (st.branches.empty())3495 return make_regex_seq(st);34963497 // OR.3498 st.branches.push_back(make_regex_seq(st));3499 return regex_node("OR", st.branches);3500}35013502// Parses a regex pattern into a tree, computing the number of ways to match the3503// pattern.3504inline regex_node parse_regex(std::string regex) {3505 std::string new_regex;3506 for (char c : regex)3507 if (c != ' ')3508 new_regex += c;3509 swap(regex, new_regex);3510 regex_state cur;3511 std::vector<regex_state> stack;35123513 for (size_t i = 0; i < regex.size(); ++i) {3514 char c = regex[i];35153516 if (c == '(') {3517 // Pushes the current state to the stack.3518 stack.push_back(std::move(cur));3519 cur = regex_state();3520 } else if (c == ')') {3521 // Finishes the current state, and adds it to the parent.3522 regex_node node = finish_regex_state(cur);35233524 tgen_ensure(!stack.empty(), "str: invalid regex: unmatched `)`");3525 cur = std::move(stack.back());3526 stack.pop_back();35273528 cur.cur.push_back(std::move(node));3529 } else if (c == '|') {3530 // Starts a new OR group.3531 regex_node node = make_regex_seq(cur);3532 cur.branches.push_back(std::move(node));3533 } else if (c == '[') {3534 // Parses a character class.3535 std::string chars;35363537 for (++i; i < regex.size() and regex[i] != ']'; ++i) {3538 if (i + 2 < regex.size() and regex[i + 1] == '-') {3539 char a = regex[i], b = regex[i + 2];3540 if (a > b)3541 std::swap(a, b);3542 for (char x = a; x <= b; ++x)3543 chars += x;3544 i += 2;3545 } else3546 chars += regex[i];3547 }35483549 tgen_ensure(i < regex.size() and regex[i] == ']',3550 "str: invalid regex: unmatched `[`");3551 cur.cur.emplace_back("[" + chars + "]");3552 } else if (c == '{') {3553 // Parses a repetition.3554 ++i;3555 int l = -1, r = -1;35563557 while (i < regex.size() and3558 isdigit(static_cast<unsigned char>(regex[i]))) {3559 if (l == -1)3560 l = 0;3561 tgen_ensure(l <= static_cast<int>(1e8),3562 "str: invalid regex: number too large inside `{}`");3563 l = 10 * l + (regex[i] - '0');3564 ++i;3565 }35663567 if (i < regex.size() and regex[i] == ',') {3568 ++i;3569 while (i < regex.size() and3570 isdigit(static_cast<unsigned char>(regex[i]))) {3571 if (r == -1)3572 r = 0;3573 tgen_ensure(3574 r <= static_cast<int>(1e8),3575 "str: invalid regex: number too large inside `{}`");3576 r = 10 * r + (regex[i] - '0');3577 ++i;3578 }3579 } else3580 r = l;35813582 tgen_ensure(i < regex.size() and regex[i] == '}',3583 "str: invalid regex: unmatched `{`");3584 tgen_ensure(l != -1 and r != -1,3585 "str: invalid regex: missing number inside `{}`");3586 tgen_ensure(l <= r,3587 "str: invalid regex: invalid range inside `{}`");35883589 // Creates a REP node from the previous node.3590 tgen_ensure(!cur.cur.empty(),3591 "str: invalid regex: expected expression before `{}`");35923593 regex_node rep(l, r, cur.cur.back());3594 cur.cur.pop_back();3595 cur.cur.push_back(std::move(rep));3596 } else {3597 // Creates a char node.3598 cur.cur.emplace_back(std::string(1, c));3599 }3600 }36013602 tgen_ensure(stack.empty(), "str: invalid regex: unmatched `(`");3603 return finish_regex_state(cur);3604}36053606// Generates a uniformly random string that matches the given regex.3607inline void gen_regex(const regex_node &node, std::string &str) {3608 // For [chars], generate a random character from the list.3609 if (node.pattern_[0] == '[') {3610 str += node.pattern_[1 + next<int>(0, node.pattern_.size() - 3)];3611 return;3612 }36133614 // For REP, generate a random number of times to repeat the pattern.3615 if (node.left_bound_ != -1) {3616 // Generates a random value W from 0 to num_ways.3617 // log(W) = log(random(0, 1) * num_ways)3618 // = log(random(0, 1)) + log(num_ways).3619 double log_rand = math::detail::log_space(next<double>(0, 1)) +3620 node.log_space_num_ways_;3621 double cur_prob = math::detail::LOG_ZERO;3622 double child_num_ways = node.children_[0].log_space_num_ways_;36233624 for (int i = node.left_bound_; i <= node.right_bound_; ++i) {3625 cur_prob =3626 math::detail::add_log_space(cur_prob, i * child_num_ways);3627 if (log_rand <= cur_prob) {3628 for (int j = 0; j < i; ++j)3629 gen_regex(node.children_[0], str);3630 return;3631 }3632 }36333634 tgen_ensure_against_bug(false,3635 "str: log_rand > cur_prob in REP gen_regex");3636 }36373638 // For SEQ, generate all children.3639 if (!node.children_.empty() and node.pattern_ == "SEQ") {3640 for (const regex_node &child : node.children_)3641 gen_regex(child, str);3642 return;3643 }36443645 // For OR, generate a random child.3646 if (!node.children_.empty() and node.pattern_ == "OR") {3647 // Generates a random value W from 0 to num_ways.3648 // log(W) = log(random(0, 1) * num_ways)3649 // = log(random(0, 1)) + log(num_ways).3650 double log_rand = math::detail::log_space(next<double>(0, 1)) +3651 node.log_space_num_ways_;3652 double cur_prob = math::detail::LOG_ZERO;36533654 for (const regex_node &child : node.children_) {3655 cur_prob = math::detail::add_log_space(cur_prob,3656 child.log_space_num_ways_);3657 if (log_rand <= cur_prob) {3658 gen_regex(child, str);3659 return;3660 }3661 }36623663 tgen_ensure_against_bug(false,3664 "str: log_rand > cur_prob in OR gen_regex");3665 }36663667 // For char, generate the character.3668 detail::tgen_ensure_against_bug(3669 node.pattern_.size() == 1,3670 "str: invalid regex: expected single character, but got `" +3671 node.pattern_ + "`");3672 str += node.pattern_[0];3673}36743675// Formats a regex string with given arguments.3676template <typename... Args>3677std::string regex_format(const std::string &s, Args &&...args) {3678 if constexpr (sizeof...(Args) == 0) {3679 return s;3680 } else {3681 int size = std::snprintf(nullptr, 0, s.c_str(), args...) + 1;3682 std::string buf(size, '\0');3683 std::snprintf(buf.data(), size, s.c_str(), args...);3684 buf.pop_back(); // remove '\0'3685 return buf;3686 }3687}36883689} // namespace detail36903691/*3692 * String generator.3693 */36943695struct str : gen_base<str> {3696 std::optional<list<char>> list_; // List of characters.3697 std::optional<detail::regex_node>3698 root_; // Root node of the regex tree for the whole string.36993700 // Creates generator for strings of size 'size', with random characters in3701 // [value_left, value_right].3702 str(int size, char value_left = 'a', char value_right = 'z') {3703 tgen_ensure(size > 0, "str: size must be positive");3704 list_ = list<char>(size, value_left, value_right);3705 }37063707 // Creates generator for strings of size 'size', with random characters in3708 // 'chars'.3709 str(int size, std::set<char> chars) {3710 tgen_ensure(size > 0, "str: size must be positive");3711 list_ = list<char>(size, chars);3712 }37133714 // Creates generator for strings that match the given regex.3715 template <typename... Args> str(const std::string ®ex, Args &&...args) {3716 tgen_ensure(regex.size() > 0, "str: regex must be non-empty");37173718 root_ = detail::parse_regex(3719 detail::regex_format(regex, std::forward<Args>(args)...));3720 }37213722 // Restricts strings for str[idx] = value.3723 str &fix(int idx, char character) {3724 tgen_ensure(!root_, "str: cannot add restriction for regex");3725 list_->fix(idx, character);3726 return *this;3727 }37283729 // Restricts strings for list[S] to be equal, for given subset S of indices.3730 str &equal(std::set<int> indices) {3731 tgen_ensure(!root_, "str: cannot add restriction for regex");3732 list_->equal(indices);3733 return *this;3734 }37353736 // Restricts strings for str[idx_1] = str[idx_2].3737 str &equal(int idx_1, int idx_2) {3738 tgen_ensure(!root_, "str: cannot add restriction for regex");3739 list_->equal(idx_1, idx_2);3740 return *this;3741 }37423743 // Restricts strings for str[left..right] to have all equal values.3744 str &equal_range(int left, int right) {3745 tgen_ensure(!root_, "str: cannot add restriction for regex");3746 list_->equal_range(left, right);3747 return *this;3748 }37493750 // Restricts strings for all equal chars.3751 str &all_equal() {3752 tgen_ensure(!root_, "str: cannot add restriction for regex");3753 list_->all_equal();3754 return *this;3755 }37563757 // Restricts strings for str[left..right] to be a palindrome.3758 str &palindrome(int left, int right) {3759 tgen_ensure(!root_, "str: cannot add restriction for regex");3760 tgen_ensure(0 <= left and left <= right and right < list_->size_,3761 "str: range indices must be valid");3762 for (int i = left; i < right - (i - left); ++i)3763 equal(i, right - (i - left));3764 return *this;3765 }37663767 // Restricts strings for the entire string to be a palindrome.3768 str &palindrome() {3769 tgen_ensure(!root_, "str: cannot add restriction for regex");3770 return palindrome(0, list_->size_ - 1);3771 }37723773 // Restricts strings for str[S] to be different (distinct), for given subset3774 // S of indices.3775 str &different(std::set<int> indices) {3776 tgen_ensure(!root_, "str: cannot add restriction for regex");3777 list_->different(indices);3778 return *this;3779 }37803781 // Restricts strings for str[idx_1] != str[idx_2].3782 str &different(int idx_1, int idx_2) {3783 tgen_ensure(!root_, "str: cannot add restriction for regex");3784 list_->different(idx_1, idx_2);3785 return *this;3786 }37873788 // Restricts lists for list[left..right] to have all different chars.3789 str &different_range(int left, int right) {3790 tgen_ensure(!root_, "str: cannot add restriction for regex");3791 list_->different_range(left, right);3792 return *this;3793 }37943795 // Restricts strings for all chars to be different.3796 str &all_different() {3797 tgen_ensure(!root_, "str: cannot add restriction for regex");3798 list_->all_different();3799 return *this;3800 }38013802 // str value.3803 struct value : gen_value_base<value> {3804 using tgen_is_sequential_tag = detail::is_sequential_tag;38053806 using value_type = char;3807 using std_type = std::string;3808 std::string str_;38093810 value(const std::string &str) : str_(str) {3811 tgen_ensure(!str_.empty(), "str: value: cannot be empty");3812 }38133814 // Fetches size.3815 int size() const { return str_.size(); }38163817 // Fetches position idx.3818 char &operator[](int idx) {3819 tgen_ensure(0 <= idx and idx < size(),3820 "str: value: index out of bounds");3821 return str_[idx];3822 }3823 const char &operator[](int idx) const {3824 tgen_ensure(0 <= idx and idx < size(),3825 "str: value: index out of bounds");3826 return str_[idx];3827 }38283829 // Sorts characters in non-decreasing order.3830 // O(n log n).3831 value &sort() {3832 std::sort(str_.begin(), str_.end());3833 return *this;3834 }38353836 // Reverses string.3837 // O(n).3838 value &reverse() {3839 std::reverse(str_.begin(), str_.end());3840 return *this;3841 }38423843 // Lowercases all characters.3844 // O(n).3845 value &lowercase() {3846 for (char &c : str_)3847 c = std::tolower(c);3848 return *this;3849 }38503851 // Uppercases all characters.3852 // O(n).3853 value &uppercase() {3854 for (char &c : str_)3855 c = std::toupper(c);3856 return *this;3857 }38583859 // Concatenates two values.3860 // Linear.3861 value operator+(const value &rhs) const {3862 return value(str_ + rhs.str_);3863 }38643865 // Shuffles string uniformly.3866 // O(n).3867 value &shuffle() {3868 for (int i = 0; i < size(); ++i)3869 std::swap(str_[i], str_[next(0, size() - 1)]);3870 return *this;3871 }38723873 // Returns a random character uniformly.3874 // O(1).3875 char pick() const { return str_[next<int>(0, size() - 1)]; }38763877 // Returns str_[i] with probability proportional to distribution[i].3878 // O(1).3879 template <typename Dist>3880 char pick_by_distribution(const std::vector<Dist> &distribution) const {3881 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),3882 "value and distribution must have the same size");3883 return str_[next_by_distribution(distribution)];3884 }3885 template <typename Dist>3886 char pick_by_distribution(3887 const std::initializer_list<Dist> &distribution) const {3888 return pick_by_distribution(std::vector<Dist>(distribution));3889 }38903891 // Chooses k characters uniformly, as in a subsequence of size k.3892 // O(n).3893 value choose(int k) const {3894 tgen_ensure(0 < k and k <= size(),3895 "number of elements to choose must be valid");3896 std::string new_str;3897 int need = k;3898 for (int i = 0; need > 0; ++i) {3899 int left = size() - i;3900 if (next(1, left) <= need) {3901 new_str.push_back(str_[i]);3902 need--;3903 }3904 }3905 return value(new_str);3906 }39073908 // Prints to std::ostream.3909 friend std::ostream &operator<<(std::ostream &out, const value &val) {3910 return out << val.str_;3911 }39123913 // Gets a std::string representing the value.3914 std::string to_std() const { return std_type(str_); }3915 };39163917 // Generates str value.3918 // If created from restrictions: O(n log n).3919 // If created from regex: expected linear.3920 value gen() const {3921 if (root_) {3922 // Regex.3923 std::string ret_str;3924 gen_regex(*root_, ret_str);3925 return value(ret_str);3926 } else {3927 // List.3928 std::vector<char> vec = list_->gen().to_std();3929 return value(std::string(vec.begin(), vec.end()));3930 }3931 }3932};39333934/************3935 * *3936 * PAIR *3937 * *3938 ************/39393940namespace detail {39413942// Generates pair first == second.3943// O(1).3944template <typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {3945 T L = std::max(L1, L2);3946 T R = std::min(R1, R2);39473948 tgen_ensure(L <= R, "pair: no valid values to generate");3949 T x = next<T>(L, R);3950 return {x, x};3951}39523953// Returns {R1-L1+1, R2-L2+1}.3954template <typename T>3955std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {3956 u128 n = static_cast<i128>(R1) - L1 + 1;3957 u128 m = static_cast<i128>(R2) - L2 + 1;3958 return {n, m};3959}39603961// Returns first + first+1 + ... + last,3962// num_terms terms. Avoids overflow.3963static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {3964 u128 x = first + last, y = num_terms;39653966 // x * y / 2, avoiding overflow.3967 if (x % 2 == 0)3968 x /= 2;3969 else3970 y /= 2;39713972 return x * y;3973}39743975// Generates pair first != second.3976// O(1) expected.3977template <typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {3978 auto [n, m] = get_n_and_m(L1, R1, L2, R2);39793980 T L_intersect = std::max(L1, L2);3981 T R_intersect = std::min(R1, R2);3982 u128 inter = static_cast<i128>(R_intersect) - L_intersect + 1;39833984 u128 total = n * m - inter;3985 tgen_ensure(total > 0, "pair: no valid values to generate");39863987 // Runs O(1) expected times in the worst case.3988 T a, b;3989 do {3990 a = next<T>(L1, R1);3991 b = next<T>(L2, R2);3992 } while (a == b);39933994 return {a, b};3995}39963997// For lt, splits 'second' into two regions:3998// 1) second <= R1 -> number of 'first' is (second - L1)3999// 2) second > R1 -> number of 'first' is (R1 - L1 + 1)4000// Returns {count_region1, count_region2}.4001// O(1).4002template <typename T>4003std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {4004 auto [n, m] = get_n_and_m(L1, R1, L2, R2);40054006 // 'second' must be >= L1 + 1.4007 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);4008 i128 R_second = R2;40094010 // Split point for 'second'.4011 i128 split = std::min<i128>(R_second, R1);40124013 // Region 1: b in [L_second, split].4014 u128 len1 = std::max<i128>(0, split - L_second + 1);40154016 u128 count_region1 = 0;4017 if (len1 > 0) {4018 // For b in [L_second, split], there are (b - L1) ways.4019 i128 first = L_second - L1;4020 i128 last = split - L1;40214022 // Arithmetic series first + (first + 1) + ... + last, len1 terms.4023 count_region1 = pos_arith_sum(first, last, len1);4024 }40254026 // Region 2: b > R1.4027 // For b in [R1+1, R_second], there are 'n' ways.4028 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);40294030 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);4031 u128 count_region2 = len2 * n;40324033 return {count_region1, count_region2};4034}40354036// Generates pair first < second.4037// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).4038template <typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {4039 auto [n, m] = get_n_and_m(L1, R1, L2, R2);40404041 // 'second' needs to be at least L1 + 1 to have a valid value for4042 // 'first'.4043 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);4044 i128 R_second = R2;40454046 // Splits 'second' into two regions:4047 // 1) b <= R1 -> number of 'first' is (b - L1);4048 // 2) b > R1 -> number of 'first' is (R1 - L1 + 1).4049 i128 split = std::min<i128>(R_second, R1);40504051 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);4052 u128 total = count_region1 + count_region2;4053 tgen_ensure(total > 0, "pair: no valid values to generate");40544055 u128 k = detail::next128(total);4056 if (k < count_region1) {4057 // Region 1: invert arithmetic series.40584059 // For b in [L_second, split].4060 u128 len1 = std::max<i128>(0, split - L_second + 1);40614062 // We consider b in [L_second, L_second + d].4063 // Each b contributes (b - L1) = base + (b - L_second).4064 // So we sum: base + (base+1) + ... + (base+d)4065 // d in [0, len1).40664067 i128 base = L_second - L1;4068 i128 lo = 0, hi = static_cast<i128>(len1) - 1;40694070 while (lo < hi) {4071 i128 mid = lo + (hi - lo) / 2;40724073 if (pos_arith_sum(base, base + mid, mid + 1) <= k)4074 lo = mid + 1;4075 else4076 hi = mid;4077 }4078 i128 d = lo;40794080 // Subtracts prefix sum with d-1 terms from k.4081 if (d > 0)4082 k -= pos_arith_sum(base, base + d - 1, d);40834084 return {L1 + static_cast<T>(k), L_second + d};4085 } else {4086 // Region 2: uniform block of size n.4087 k -= count_region1;40884089 // For b in [R1+1, R_second], there are 'n' ways.4090 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);40914092 return {L1 + static_cast<T>(k % n),4093 L_second_region2 + static_cast<T>(k / n)};4094 }4095}40964097// Generates pair first > second.4098// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).4099template <typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {4100 auto [first, second] = gen_lt(L2, R2, L1, R1);4101 return {second, first};4102}41034104// Generates pair first <= second.4105// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).4106template <typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {4107 // Counts how many pairs are there with first = second.4108 i128 L_intersect = std::max(L1, L2);4109 i128 R_intersect = std::min(R1, R2);4110 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);41114112 // Counts how many pairs are there with first < second.4113 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);4114 u128 lt_count = lt_region1 + lt_region2;41154116 u128 total = eq_count + lt_count;4117 tgen_ensure(total > 0, "pair: no valid values to generate");41184119 if (detail::next128(total) < eq_count)4120 return gen_eq(L1, R1, L2, R2);4121 return gen_lt(L1, R1, L2, R2);4122}41234124// Generates pair first >= second.4125// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).4126template <typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {4127 auto [first, second] = gen_leq(L2, R2, L1, R1);4128 return {second, first};4129}41304131}; // namespace detail41324133/*4134 * Pair generator.4135 *4136 * Pairs of integral types.4137 */41384139template <typename T> struct pair : gen_base<pair<T>> {4140 std::pair<T, T> first_, second_; // Range of first and second values.4141 // Type of restriction.4142 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };4143 restriction_type type_ = restriction_type::unspecified;41444145 // Creates a pair with random values in [first_l, first_r] and [second_l,4146 // second_r].4147 pair(T first_left, T first_right, T second_left, T second_right)4148 : first_(first_left, first_right), second_(second_left, second_right) {4149 tgen_ensure(first_left <= first_right,4150 "pair: first range must be valid");4151 tgen_ensure(second_left <= second_right,4152 "pair: second range must be valid");4153 }41544155 // Creates a pair with random values in [both_l, both_r].4156 pair(T both_left, T both_right)4157 : pair(both_left, both_right, both_left, both_right) {}41584159 // Restricts pair for first = second.4160 pair &eq() {4161 type_ = restriction_type::eq;4162 return *this;4163 }41644165 // Restricts pair for first != second.4166 pair &neq() {4167 type_ = restriction_type::neq;4168 return *this;4169 }41704171 // Restricts pair for first < second.4172 pair <() {4173 type_ = restriction_type::lt;4174 return *this;4175 }41764177 // Restricts pair for first > second.4178 pair >() {4179 type_ = restriction_type::gt;4180 return *this;4181 }41824183 // Restricts pair for first <= second.4184 pair &leq() {4185 type_ = restriction_type::leq;4186 return *this;4187 }41884189 // Restricts pair for first >= second.4190 pair &geq() {4191 type_ = restriction_type::geq;4192 return *this;4193 }41944195 // Pair value.4196 struct value : gen_value_base<value> {4197 using value_type = T;4198 using std_type = std::pair<T, T>;41994200 std::pair<T, T> pair_;4201 char sep_;42024203 value(const std::pair<T, T> &pair) : pair_(pair), sep_(' ') {}4204 value(const T &first, const T &second)4205 : pair_(first, second), sep_(' ') {}42064207 T first() const { return pair_.first; }4208 T second() const { return pair_.second; }42094210 // Sets the separator for the pair, for printing.4211 value &separator(char sep) {4212 sep_ = sep;4213 return *this;4214 }42154216 // Prints to std::ostream, separated by sep_.4217 friend std::ostream &operator<<(std::ostream &out, const value &val) {4218 return out << val.pair_.first << val.sep_ << val.pair_.second;4219 }42204221 // Gets a std::pair representing the value.4222 auto to_std() const {4223 if constexpr (!detail::is_generator_value<T>::value) {4224 return pair_;4225 } else {4226 std::pair<typename T::std_type, typename T::std_type> pair(4227 pair_.first.to_std(), pair_.second.to_std());4228 return pair;4229 }4230 }4231 };42324233 // Generates a random pair.4234 // O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).4235 value gen() const {4236 T L1 = first_.first, R1 = first_.second;4237 T L2 = second_.first, R2 = second_.second;42384239 switch (type_) {4240 case restriction_type::unspecified:4241 return {next<T>(L1, R1), next<T>(L2, R2)};4242 case restriction_type::eq:4243 return detail::gen_eq<T>(L1, R1, L2, R2);4244 case restriction_type::neq:4245 return detail::gen_neq<T>(L1, R1, L2, R2);4246 case restriction_type::lt:4247 return detail::gen_lt<T>(L1, R1, L2, R2);4248 case restriction_type::gt:4249 return detail::gen_gt<T>(L1, R1, L2, R2);4250 case restriction_type::leq:4251 return detail::gen_leq<T>(L1, R1, L2, R2);4252 case restriction_type::geq:4253 return detail::gen_geq<T>(L1, R1, L2, R2);4254 }4255 throw detail::error("pair: unknown restriction type");4256 }4257};42584259/************4260 * *4261 * TREE *4262 * *4263 ************/42644265namespace detail {42664267// Generates edges from Prufer sequence.4268// O(n).4269inline std::vector<std::pair<int, int>> edges_from_prufer(std::vector<int> p) {4270 int n = p.size() + 2;42714272 // Degrees.4273 std::vector<int> d(n, 1);4274 for (int i : p)4275 d[i]++;42764277 // Adds last vertex.4278 p.push_back(n - 1);42794280 // Finds first vertex with degree 1.4281 int idx, u;4282 idx = u = find(d.begin(), d.end(), 1) - d.begin();42834284 // Generates edges.4285 std::vector<std::pair<int, int>> edges;4286 for (int v : p) {4287 edges.emplace_back(u, v);4288 if (--d[v] == 1 and v < idx)4289 u = v;4290 else4291 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();4292 }4293 return edges;4294}42954296// Disjoint set union (union-find) for connectivity queries.4297struct dsu {4298 std::vector<int> parent_;4299 std::vector<unsigned char> rank_;43004301 // Creates a dsu with `n` elements, indexed from 0 to n-1.4302 // Initially every element is in its own set.4303 // O(n).4304 dsu(int n) : parent_(n), rank_(n, 0) {4305 for (int i = 0; i < n; ++i)4306 parent_[i] = i;4307 }43084309 // Adds new elements to the dsu, each in their own new set.4310 // O(k) amortized.4311 void add_elements(int k) {4312 for (int i = 0; i < k; ++i) {4313 int new_id = parent_.size();4314 parent_.push_back(new_id);4315 rank_.push_back(0);4316 }4317 }43184319 // Finds representative of set containing i.4320 // O(alpha(n)) amortized, O(log n) worst case.4321 int find(int i) {4322 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);4323 }43244325 // Merges components of `a` and `b`. Returns if the sets were united, and4326 // false if a and b were in the same set.4327 // O(alpha(n)) amortized, O(log n) worst case.4328 bool unite(int a, int b) {4329 a = find(a);4330 b = find(b);4331 if (a == b)4332 return false;4333 if (rank_[a] > rank_[b])4334 std::swap(a, b);4335 parent_[a] = b;4336 if (rank_[a] == rank_[b])4337 ++rank_[b];4338 return true;4339 }4340};43414342} // namespace detail43434344// Forward declaration of wgraph.4345template <typename VWeight, typename EWeight> struct wgraph;43464347/*4348 * Tree generator.4349 *4350 * Unrooted trees with `n` vertices, indexed from 0 to n-1.4351 * These are unrooted undirected labeled trees, that is, isomorphism is not4352 * taken into account. VWeight is the type of vertex weights, and EWeight is4353 * the type of edge weights. Generator does not generate weights. The weights4354 * are to be set in the wtree::value.4355 */43564357template <typename VWeight, typename EWeight>4358struct wtree : gen_base<wtree<VWeight, EWeight>> {4359 int n_; // Number of vertices.4360 std::set<std::pair<int, int>> edges_; // Edges that were set.43614362 // Creates tree generator with `n` vertices.4363 // O(1).4364 wtree(int n) : n_(n) {4365 tgen_ensure(n > 0, "wtree: number of vertices must be positive");4366 }43674368 // Adds edge between u and v (this edge must be generated).4369 // O(log n).4370 wtree &add_edge(int u, int v) {4371 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,4372 "wtree: vertices must be indexed in [0, n)");4373 tgen_ensure(u != v, "wtree: cannot add self loop to tree");43744375 if (u > v)4376 std::swap(u, v);4377 edges_.emplace(u, v);4378 return *this;4379 }43804381 // Tree value.4382 //4383 // Edges are stored in both directions in adjacency list, but only u < v in4384 // edge list.4385 struct value : gen_value_base<value> {4386 using std_type = std::pair<int, std::vector<std::set<int>>>;43874388 int n_; // Number of vertices.4389 std::vector<std::set<int>> adj_; // Adjacency list.4390 std::vector<std::pair<int, int>> edges_; // Edge list.4391 bool add_1_; // If should add 1 for printing vertex ids.4392 bool print_n_; // If should print n.4393 std::optional<int> print_parents_; // If should print in parent style4394 // (stores the root).4395 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.4396 std::optional<std::vector<EWeight>>4397 edge_weights_; // Edge weights (in same order as edges_).4398 detail::dsu dsu_; // Connectivity of current edges (for cycle checks).43994400 // Creates value from adjacency list.4401 // O(n).4402 value(const std::vector<std::set<int>> &adj)4403 : n_(static_cast<int>(adj.size())), adj_(adj), add_1_(false),4404 print_n_(false), dsu_(n_) {4405 for (int u = 0; u < n_; ++u)4406 for (auto v : adj[u]) {4407 tgen_ensure(4408 0 <= v and v < n_,4409 "wtree: value: vertices must be indexed in [0, n)");4410 // Symmetric adjacency: count each undirected edge once.4411 if (u < v) {4412 edges_.emplace_back(u, v);4413 tgen_ensure(4414 dsu_.unite(u, v),4415 "wtree: value: initial graph must form a tree");4416 }4417 }4418 }44194420 // Creates value from `n` and edge list.4421 // O(n).4422 value(int n, const std::vector<std::pair<int, int>> &edges)4423 : n_(n), adj_(n), add_1_(false), print_n_(false), dsu_(n) {4424 edges_.reserve(edges.size());4425 for (auto [u, v] : edges) {4426 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n,4427 "wtree: value: vertices must be indexed in [0, n)");4428 tgen_ensure(dsu_.unite(u, v),4429 "wtree: value: initial graph must form a tree");4430 if (u > v)4431 std::swap(u, v);4432 edges_.emplace_back(u, v);4433 adj_[u].insert(v);4434 adj_[v].insert(u);4435 }4436 }4437 value(int n, const std::set<std::pair<int, int>> &edges)4438 : value(n, std::vector<std::pair<int, int>>(edges.begin(),4439 edges.end())) {}4440 value(int n, const std::initializer_list<std::pair<int, int>> &edges)4441 : value(n, std::vector<std::pair<int, int>>(edges)) {}44424443 // Creates tree from graph via Kruskal-like random spanning tree.4444 // Implemented after wgraph definition.4445 // O(n + m alpha(n)).4446 value(const typename wgraph<VWeight, EWeight>::value &g);44474448 // Weight type conversion.4449 // O(n).4450 template <typename NewVWeight, typename NewEWeight>4451 typename wtree<NewVWeight, NewEWeight>::value4452 convert_weight_types() const {4453 tgen_ensure(!vertex_weights_.has_value() and4454 !edge_weights_.has_value(),4455 "wtree: value: cannot convert weight type after "4456 "assigning weights");44574458 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);4459 new_tree.add_1_ = add_1_;4460 new_tree.print_n_ = print_n_;4461 new_tree.print_parents_ = print_parents_;4462 return new_tree;4463 }44644465 // Fetches number of vertices.4466 int n() const { return n_; }44674468 // Fetches a const ref. to adjacency list.4469 const std::vector<std::set<int>> &adj() const { return adj_; }44704471 // Fetches a const ref. to edge list.4472 const std::vector<std::pair<int, int>> &edges() const { return edges_; }44734474 // Fetches a const ref. to vertex weights.4475 const std::optional<std::vector<VWeight>> &vertex_weights() const {4476 return vertex_weights_;4477 }44784479 // Fetches a const ref. to edge weights.4480 const std::optional<std::vector<EWeight>> &edge_weights() const {4481 return edge_weights_;4482 }44834484 // Sets vertex weights.4485 // O(n).4486 template <typename NewVWeight = VWeight>4487 typename wtree<NewVWeight, EWeight>::value set_vertex_weights(4488 const std::vector<NewVWeight> &vertex_weights) const {4489 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),4490 "wtree: value: must give `n` vertex weights");44914492 auto new_tree = convert_weight_types<NewVWeight, EWeight>();4493 new_tree.vertex_weights_ = vertex_weights;4494 return new_tree;4495 }44964497 // Sets edge weights.4498 // O(n).4499 template <typename NewEWeight = EWeight>4500 typename wtree<VWeight, NewEWeight>::value4501 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {4502 tgen_ensure(4503 edge_weights.size() == edges().size(),4504 "wtree: value: must give `edges().size()` edge weights");45054506 auto new_tree = convert_weight_types<VWeight, NewEWeight>();4507 new_tree.edge_weights_ = edge_weights;4508 return new_tree;4509 }45104511 // Enables edge-weighted mode before adding weighted edges4512 // incrementally. The tree must have no edges yet. O(1).4513 value &edge_weighted() {4514 tgen_ensure(edges().size() == 0,4515 "wtree: value: edge_weighted requires a tree with no "4516 "edges");4517 tgen_ensure(!edge_weights_.has_value(),4518 "wtree: value: tree is already edge-weighted");45194520 edge_weights_ = std::vector<EWeight>();4521 return *this;4522 }45234524 // Adds 1 to vertex ids, for printing.4525 // O(1).4526 value &add_1() {4527 add_1_ = true;4528 return *this;4529 }45304531 // Prints `n` on a new line before printing the tree.4532 // O(1).4533 value &print_n() {4534 print_n_ = true;4535 return *this;4536 }45374538 // Prints the tree in parent style.4539 // If root = -1, the root is considered to be 0, and its parent is not4540 // printed. Otherwise, prints the parent of the root as -1. If root = n,4541 // randomizes the root. O(1).4542 value &print_parents(int root = -1) {4543 tgen_ensure(root == -1 or (0 <= root and root < n()) or root == n(),4544 "wtree: value: root must be -1, `n`, or in [0, n)");4545 print_parents_ = root;4546 return *this;4547 }45484549 // Shuffles the tree's vertex labels (except those in `indices`,4550 // which keep their current label) and edge order. The change is4551 // applied eagerly to the underlying adjacency list, edge list,4552 // vertex weights and edge weights.4553 // O(n).4554 value &shuffle_except(std::set<int> indices) {4555 // Builds the relabeling: for each vertex `i`, `new_label[i]` is4556 // its new id. Vertices in `indices` keep their label; the others4557 // are permuted among themselves.4558 std::vector<int> new_label(n());4559 std::vector<int> shuffled;4560 for (int i = 0; i < n(); ++i) {4561 if (indices.count(i))4562 new_label[i] = i;4563 else4564 shuffled.push_back(i);4565 }4566 std::vector<int> targets = shuffled;4567 tgen::shuffle(targets.begin(), targets.end());4568 for (size_t k = 0; k < shuffled.size(); ++k)4569 new_label[shuffled[k]] = targets[k];45704571 // Rewrites adjacency list with new labels.4572 std::vector<std::set<int>> new_adj(n());4573 for (int u = 0; u < n(); ++u)4574 for (int v : adj_[u])4575 new_adj[new_label[u]].insert(new_label[v]);4576 adj_ = std::move(new_adj);45774578 // Rewrites edges with new labels (canonical undirected order).4579 for (auto &[u, v] : edges_) {4580 u = new_label[u];4581 v = new_label[v];4582 if (u > v)4583 std::swap(u, v);4584 }45854586 // Permutes vertex weights to match the new labels.4587 if (vertex_weights_.has_value()) {4588 std::vector<VWeight> new_vw(n());4589 for (int i = 0; i < n(); ++i)4590 new_vw[new_label[i]] = (*vertex_weights_)[i];4591 vertex_weights_ = std::move(new_vw);4592 }45934594 // Rebuilds the dsu so future `add_edge` calls see the new labels.4595 dsu_ = detail::dsu(n());4596 for (auto [u, v] : edges_)4597 dsu_.unite(u, v);45984599 // Shuffles edge order, keeping edge weights aligned.46004601 std::vector<int> perm(edges_.size());4602 std::iota(perm.begin(), perm.end(), 0);4603 tgen::shuffle(perm.begin(), perm.end());46044605 std::vector<std::pair<int, int>> new_edges;4606 std::optional<std::vector<EWeight>> new_ew;4607 if (edge_weights_.has_value())4608 new_ew = std::vector<EWeight>();4609 for (int i : perm) {4610 new_edges.push_back(edges_[i]);4611 if (new_ew.has_value())4612 new_ew->push_back((*edge_weights_)[i]);4613 }4614 edges_ = new_edges;4615 if (new_ew.has_value())4616 edge_weights_ = new_ew;46174618 return *this;4619 }46204621 // Shuffles the tree's vertices and edge order.4622 // O(n).4623 value &shuffle() { return shuffle_except({}); }46244625 // Adds edge (u, v).4626 // O(log n) amortized.4627 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {4628 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),4629 "wtree: value: vertex ids must be valid");46304631 if (u > v)4632 std::swap(u, v);46334634 if (adj_[u].count(v))4635 return *this;46364637 adj_[u].insert(v);4638 adj_[v].insert(u);4639 edges_.emplace_back(u, v);4640 tgen_ensure(dsu_.unite(u, v),4641 "wtree: value: added edge must not create a cycle");46424643 if (w.has_value()) {4644 tgen_ensure(edge_weights().has_value(),4645 "wtree: value: cannot add weighted edge to "4646 "edge-unweighted tree");46474648 edge_weights_->push_back(*w);4649 } else4650 tgen_ensure(!edge_weights().has_value(),4651 "wtree: value: cannot add unweighted edge to "4652 "edge-weighted tree");46534654 return *this;4655 }46564657 // Links tree with another `rhs`, adding the edge between u (in left4658 // tree) and v (in right tree). Ids for added vertices are updated4659 // accordingly.4660 // O(rhs.n + rhs.m * log n) amortized.4661 value &link(const value &rhs, int new_u, int new_v,4662 std::optional<EWeight> new_w = std::nullopt) {4663 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and4664 new_v < rhs.n(),4665 "wtree: value: vertex ids must be valid");46664667 // Edges from right-hand side.4668 int shift = n();4669 add_vertices(rhs.n(), rhs.vertex_weights());4670 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {4671 auto [u, v] = rhs.edges()[i];4672 add_edge(shift + u, shift + v,4673 rhs.edge_weights().has_value()4674 ? std::optional<EWeight>((*rhs.edge_weights())[i])4675 : std::nullopt);4676 }46774678 // New edge.4679 add_edge(new_u, shift + new_v, new_w);46804681 return *this;4682 }46834684 // Glues the tree with another `rhs` such that index_pairs[i].first is4685 // considered to be the same as index_pairs[i].second. Ids for added4686 // vertices are updated accordingly.4687 // O(rhs.n + rhs.m * log n) amortized.4688 value &glue(const value &rhs,4689 std::set<std::pair<int, int>> index_pairs) {4690 // Checks validity of indices.4691 std::set<int> idx_left, idx_right;4692 std::vector<int> right_id_to_left(rhs.n(), -1);4693 for (auto [l, r] : index_pairs) {4694 tgen_ensure(4695 0 <= l and l < n() and 0 <= r and r < rhs.n(),4696 "wtree: value: vertex indices to glue must be valid");4697 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,4698 "wtree: value: must not have repeated indices "4699 "on the same side to glue");47004701 idx_left.insert(l);4702 idx_right.insert(r);4703 right_id_to_left[r] = l;4704 }47054706 // Computes new ids of right vertices.4707 std::vector<int> new_right_id(rhs.n(), -1);4708 int intersection_lt = 0;4709 std::optional<std::vector<VWeight>> rhs_vertex_weights;4710 for (int i = 0; i < rhs.n(); ++i) {4711 if (right_id_to_left[i] != -1) {4712 // Is in intersection.4713 ++intersection_lt;4714 new_right_id[i] = right_id_to_left[i];4715 } else {4716 // New id.4717 new_right_id[i] = n() + i - intersection_lt;4718 if (rhs.vertex_weights().has_value()) {4719 if (!rhs_vertex_weights.has_value())4720 rhs_vertex_weights = std::vector<VWeight>();4721 rhs_vertex_weights->push_back(4722 (*rhs.vertex_weights())[i]);4723 }4724 }4725 }47264727 // Adds new vertices and edges.4728 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);4729 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {4730 auto [u, v] = rhs.edges()[i];4731 add_edge(new_right_id[u], new_right_id[v],4732 rhs.edge_weights().has_value()4733 ? std::optional<EWeight>((*rhs.edge_weights())[i])4734 : std::nullopt);4735 }47364737 return *this;4738 }4739 value &glue(const value &rhs,4740 std::initializer_list<std::pair<int, int>> il) {4741 return glue(rhs, std::set<std::pair<int, int>>(il));4742 }47434744 // Glues the tree with another `rhs` at `indices`. That is, idx in4745 // `indices` are considered to be the same vertex. Ids for added4746 // vertices are updated accordingly.4747 // O(rhs.n).4748 value &glue(const value &rhs, std::set<int> indices) {4749 std::set<std::pair<int, int>> index_pairs;4750 for (auto i : indices)4751 index_pairs.emplace(i, i);4752 return glue(rhs, index_pairs);4753 }4754 value &glue(const value &rhs, const std::initializer_list<int> &il) {4755 return glue(rhs, std::set<int>(il));4756 }47574758 // Prints to std::ostream.4759 // O(n).4760 friend std::ostream &operator<<(std::ostream &out, const value &val) {4761 if (val.print_n_)4762 out << val.n() << '\n';47634764 // Prints vertex weights.4765 if (val.vertex_weights()) {4766 for (int i = 0; i < val.n(); ++i) {4767 if (i > 0)4768 out << " ";4769 out << (*val.vertex_weights())[i];4770 }4771 out << '\n';4772 }47734774 tgen_ensure(static_cast<int>(val.edges().size()) == val.n() - 1,4775 "wtree: value: invalid tree to print (number of edges "4776 "must be `n` - 1)");47774778 // Prints in parent style.4779 if (val.print_parents_.has_value()) {4780 tgen_ensure(!val.edge_weights().has_value(),4781 "wtree: value: cannot print parent style if edges "4782 "are weighted");47834784 int root = *val.print_parents_;4785 bool skip_parent_0 = root == -1;4786 if (root == -1)4787 root = 0;4788 if (root == val.n())4789 root = next(0, val.n() - 1);47904791 std::vector<int> parent(val.n(), -1);47924793 std::queue<int> q;4794 std::vector<int> vis(val.n(), false);4795 q.push(root);4796 vis[root] = true;47974798 while (q.size()) {4799 int u = q.front();4800 q.pop();4801 for (int v : val.adj()[u])4802 if (!vis[v]) {4803 vis[v] = true;4804 q.push(v);4805 parent[v] = u;4806 }4807 }48084809 if (skip_parent_0) {4810 for (int i = 1; i < val.n(); ++i) {4811 tgen_ensure(4812 parent[i] < i,4813 "wtree: value: parent of i must be less than i for "4814 "printing in parent style if root is -1");48154816 if (i > 1)4817 out << " ";4818 out << parent[i] + val.add_1_;4819 }4820 } else {4821 for (int i = 0; i < val.n(); ++i) {4822 if (i > 0)4823 out << " ";4824 out << (parent[i] == -1 ? -1 : parent[i]) + val.add_1_;4825 }4826 }48274828 out << '\n';4829 return out;4830 }48314832 // Prints edges.4833 for (int i = 0; i < static_cast<int>(val.edges().size()); ++i) {4834 auto [u, v] = val.edges()[i];4835 out << (u + val.add_1_) << " " << (v + val.add_1_);48364837 // Edge weight.4838 if (val.edge_weights().has_value())4839 out << " " << (*val.edge_weights())[i];48404841 out << '\n';4842 }48434844 return out;4845 }48464847 // Gets a std::pair<n, adj> representing the value.4848 std::pair<int, std::vector<std::set<int>>> to_std() const {4849 return std_type(n_, adj_);4850 }48514852 private:4853 // Adds `k` vertices to the tree (labeled n, n+1, ...n+k-1). Updates4854 // `n` accordingly. This makes the tree invalid (not a tree anymore).4855 // O(k) amortized.4856 value &add_vertices(int k, std::optional<std::vector<VWeight>>4857 new_vertex_weights = std::nullopt) {4858 n_ += k;4859 adj_.resize(n());4860 if (new_vertex_weights.has_value()) {4861 tgen_ensure(vertex_weights().has_value(),4862 "wtree: value: cannot add weighted vertices to "4863 "vertex-unweighted tree");4864 tgen_ensure(4865 static_cast<int>(new_vertex_weights->size()) == k,4866 "wtree: value: number of vertex weights must be equal "4867 "to number of added vertices");48684869 vertex_weights_->insert(vertex_weights_->end(),4870 new_vertex_weights->begin(),4871 new_vertex_weights->end());4872 } else4873 tgen_ensure(!vertex_weights().has_value(),4874 "wtree: value: cannot add unweighted vertices to "4875 "vertex-weighted tree");48764877 dsu_.add_elements(k);48784879 return *this;4880 }4881 };48824883 // Generates tree value.4884 // O(n).4885 value gen() const {4886 // Constructs adjacency list.4887 std::vector<std::vector<int>> adj(n_);4888 for (auto [u, v] : edges_) {4889 adj[u].push_back(v);4890 adj[v].push_back(u);4891 }48924893 std::vector<int> comp_size;4894 std::vector<std::vector<int>> component_ids;4895 std::vector<bool> vis(n_, false);4896 std::queue<int> q;48974898 for (int i = 0; i < n_; ++i) {4899 if (vis[i])4900 continue;49014902 vis[i] = true;4903 q.push(i);4904 comp_size.push_back(0);4905 component_ids.emplace_back();4906 while (q.size()) {4907 int u = q.front();4908 q.pop();4909 ++comp_size.back();4910 component_ids.back().push_back(u);4911 for (int v : adj[u]) {4912 if (!vis[v]) {4913 vis[v] = true;4914 q.push(v);4915 }4916 }4917 }4918 }49194920 // Creates edges connecting the connected components by treating them as4921 // vertices.4922 std::vector<std::pair<int, int>> new_edges(edges_.begin(),4923 edges_.end());4924 if (comp_size.size() > 1) {4925 std::vector<int> prufer_values =4926 many_by_distribution(comp_size.size() - 2, comp_size);4927 for (auto [u, v] : detail::edges_from_prufer(prufer_values))4928 new_edges.emplace_back(pick(component_ids[u]),4929 pick(component_ids[v]));4930 }49314932 return value(n_, new_edges);4933 }49344935 // Generates a (not uniformly) random skewed tree.4936 // Vertex 0 is the root. For each i in 1 .. n-1, parent(i) is4937 // wnext(i, elongation), i.e. a value in [0, i) with skew controlled by4938 // elongation (see wnext).4939 // If elongation is small enough, generates a star (center 0).4940 // If elongation is large enough, generates a path (endpoints 0 and n-1).4941 // O(n).4942 static value gen_skewed(int n, int elongation) {4943 std::vector<std::pair<int, int>> edges;4944 for (int i = 1; i < n; ++i)4945 edges.emplace_back(i, wnext<int>(i, elongation));4946 return value(n, edges);4947 }49484949 // Kruskal-like random tree: random vertex pairs until connected.4950 // Not uniformly random.4951 // O(n log(n) alpha(n)) expected.4952 static value gen_kruskal(int n) {4953 tgen_ensure(n > 0, "wtree: gen_kruskal: n must be positive");4954 if (n == 1)4955 return value(1, {});49564957 detail::dsu components(n);4958 std::vector<std::pair<int, int>> edges;4959 edges.reserve(n - 1);4960 while (edges.size() < size_t(n - 1)) {4961 int u = next(0, n - 1);4962 int v = next(0, n - 1);4963 if (u == v)4964 continue;4965 if (components.unite(u, v))4966 edges.emplace_back(u, v);4967 }4968 return value(n, edges);4969 }4970};49714972/*4973 * Other types of weighted-ness.4974 */49754976// Vertex weighted tree.4977template <typename VWeight> using vtree = wtree<VWeight, int>;49784979// Edge weighted tree.4980template <typename EWeight> using etree = wtree<int, EWeight>;49814982// Unweighted tree.4983using tree = wtree<int, int>;49844985/*************4986 * *4987 * GRAPH *4988 * *4989 *************/49904991namespace detail {49924993// Canonical undirected edge key for duplicate detection; stores (min(u, v),4994// max(u, v)). O(1).4995inline uint64_t undirected_edge_key(int u, int v) {4996 if (u > v)4997 std::swap(u, v);4998 return (static_cast<uint64_t>(u) << 32) |4999 static_cast<uint64_t>(static_cast<uint32_t>(v));5000}50015002// Directed edge key for duplicate detection; stores (u, v).5003// O(1).5004inline uint64_t directed_edge_key(int u, int v) {5005 return (static_cast<uint64_t>(u) << 32) |5006 static_cast<uint64_t>(static_cast<uint32_t>(v));5007}50085009// Maximum number of edges in a simple graph on n vertices.5010// O(1).5011inline long long max_graph_edges(int n, bool directed, bool self_loops) {5012 if (n <= 0)5013 return 0;5014 if (directed)5015 return self_loops ? static_cast<long long>(n) * n5016 : static_cast<long long>(n) * (n - 1);5017 return self_loops ? static_cast<long long>(n) * (n + 1) / 25018 : static_cast<long long>(n) * (n - 1) / 2;5019}50205021// Uniform random edge for rejection sampling.5022// O(1) expected.5023inline std::pair<int, int> get_random_graph_edge(int n, bool directed,5024 bool self_loops) {5025 if (directed) {5026 if (self_loops)5027 return {next<int>(0, n - 1), next<int>(0, n - 1)};5028 int u = next<int>(0, n - 1);5029 int v = next<int>(0, n - 1);5030 while (u == v)5031 v = next<int>(0, n - 1);5032 return {u, v};5033 }5034 if (self_loops) {5035 int u = next<int>(0, n - 1);5036 int v = next<int>(0, n - 1);5037 if (u > v)5038 std::swap(u, v);5039 return {u, v};5040 }5041 int u = next<int>(0, n - 1);5042 int v = next<int>(0, n - 1);5043 while (u == v)5044 v = next<int>(0, n - 1);5045 if (u > v)5046 std::swap(u, v);5047 return {u, v};5048}50495050// Decodes a linear edge index to (u, v) for an undirected simple graph,5051// with u < v.5052// O(log n).5053inline std::pair<int, int> decode_undirected_simple_edge(int n, long long idx) {5054 auto base = [&](int u) -> long long {5055 return static_cast<long long>(u) * (n - 1) -5056 static_cast<long long>(u) * (u - 1) / 2;5057 };5058 int lo = 0, hi = n - 2;5059 while (lo < hi) {5060 int mid = (lo + hi + 1) / 2;5061 if (base(mid) <= idx)5062 lo = mid;5063 else5064 hi = mid - 1;5065 }5066 return {lo, lo + 1 + int(idx - base(lo))};5067}50685069// Decodes a linear edge index to (u, v) for an undirected graph with loops,5070// with u <= v.5071// O(log n).5072inline std::pair<int, int> decode_undirected_loops_edge(int n, long long idx) {5073 auto base = [&](int u) -> long long {5074 return static_cast<long long>(u) * n -5075 static_cast<long long>(u) * (u - 1) / 2;5076 };5077 int lo = 0, hi = n - 1;5078 while (lo < hi) {5079 int mid = (lo + hi + 1) / 2;5080 if (base(mid) <= idx)5081 lo = mid;5082 else5083 hi = mid - 1;5084 }5085 return {lo, lo + int(idx - base(lo))};5086}50875088// Decodes a linear edge index to (u, v) for a directed simple graph (no loops).5089// O(1).5090inline std::pair<int, int> decode_directed_simple_edge(int n, long long idx) {5091 int u = idx / (n - 1);5092 int rem = idx % (n - 1);5093 return {u, rem + (rem >= u)};5094}50955096// Decodes a linear edge index according to graph mode.5097// O(log n) for undirected, O(1) for directed.5098inline std::pair<int, int>5099decode_graph_edge_index(int n, long long idx, bool directed, bool self_loops) {5100 if (directed) {5101 if (self_loops)5102 return {int(idx / n), int(idx % n)};5103 return decode_directed_simple_edge(n, idx);5104 }5105 if (self_loops)5106 return decode_undirected_loops_edge(n, idx);5107 return decode_undirected_simple_edge(n, idx);5108}51095110} // namespace detail51115112/*5113 * Graph generator.5114 *5115 * Graphs of `n` vertices labeled from 0 to n-1 and `m` edges.5116 * These are labeled graphs, that is, isomorphism is not taken into5117 * account. VWeight is the type of vertex weights, and EWeight is the type of5118 * edge weights. Generator does not generate weights. The weights are to be set5119 * in the wgraph::value.5120 */51215122template <typename VWeight, typename EWeight>5123struct wgraph : gen_base<wgraph<VWeight, EWeight>> {5124 int n_, m_; // Number of vertices and edges.5125 std::set<std::pair<int, int>> edges_; // Edges that were set.5126 bool is_directed_; // If graph is directed.5127 bool has_self_loops_; // If self-loops are allowed.51285129 // Creates graph generator with `n` vertices and `m` edges.5130 // Additionally, you can set if the graph is directed and if self loops are5131 // allowed.5132 // O(1).5133 wgraph(int n, int m, bool is_directed = false, bool has_self_loops = false)5134 : n_(n), m_(m), is_directed_(is_directed),5135 has_self_loops_(has_self_loops) {5136 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");5137 }51385139 // Adds edge between u and v (this edge must be generated).5140 // O(log m).5141 wgraph &add_edge(int u, int v) {5142 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,5143 "wgraph: vertices must be indexed in [0, n)");51445145 if (!is_directed_ and u > v)5146 std::swap(u, v);5147 edges_.emplace(u, v);5148 tgen_ensure(static_cast<int>(edges_.size()) <= m_,5149 "wgraph: too many edges were added");5150 return *this;5151 }51525153 // Graph value.5154 //5155 // Edges are stored in both directions (if undirected) in adjacency list,5156 // but only u < v in edge list.5157 // Optimized for performance (lazy adjacency list; edge-list constructor5158 // stores edges only).5159 struct value : gen_value_base<value> {5160 using std_type = std::tuple<int, int, std::vector<std::set<int>>>;51615162 int n_; // Number of vertices.5163 std::vector<std::set<int>> adj_; // Adjacency list.5164 std::vector<std::pair<int, int>> edges_; // Edge list.5165 bool is_directed_; // If graph is directed.5166 bool add_1_; // If should add 1 for printing vertex ids.5167 bool print_nm_; // If should print n and m.5168 mutable bool adj_built_{5169 false}; // Lazy cache: true once adj_ is built from edges_; mutable5170 // so const adj() can populate it.5171 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.5172 std::optional<std::vector<EWeight>>5173 edge_weights_; // Edge weights (in same order as edges_ ).51745175 // Creates value from adjacency list. The edges5176 // are considered to be directed.5177 // O(n + m).5178 value(const std::vector<std::set<int>> &adj, bool is_directed = false)5179 : n_(static_cast<int>(adj.size())), adj_(adj),5180 is_directed_(is_directed), add_1_(false), print_nm_(false),5181 adj_built_(true) {5182 for (int u = 0; u < n_; ++u)5183 for (auto v : adj[u]) {5184 tgen_ensure(5185 0 <= v and v < n_,5186 "wgraph: value: vertices must be indexed in [0, n)");5187 // Undirected adjacency is symmetric: count each edge once5188 // (canonical u <= v). Directed: every out-edge appears5189 // once.5190 if (is_directed_ or u <= v)5191 edges_.emplace_back(u, v);5192 }5193 }51945195 // Creates value from `n`, `m`, and edge list. The edges are5196 // considered to be directed.5197 // Optimized for performance (lazy adjacency list; unordered_set dedup).5198 // O(m log m).5199 value(int n, const std::vector<std::pair<int, int>> &edges = {},5200 bool is_directed = false)5201 : n_(n), edges_(), is_directed_(is_directed), add_1_(false),5202 print_nm_(false), adj_built_(false) {5203 edges_.reserve(edges.size());5204 std::unordered_set<uint64_t> seen;5205 seen.reserve(edges.size() * 2 + 1);5206 for (auto [u, v] : edges) {5207 tgen_ensure(5208 0 <= std::min(u, v) and std::max(u, v) < n,5209 "wgraph: value: vertices must be indexed in [0, n)");5210 if (!is_directed_ and u > v)5211 std::swap(u, v);5212 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)5213 : detail::undirected_edge_key(u, v);5214 if (seen.insert(key).second)5215 edges_.emplace_back(u, v);5216 }5217 }5218 value(int n, const std::set<std::pair<int, int>> &edges,5219 bool is_directed = false)5220 : value(5221 n,5222 std::vector<std::pair<int, int>>(edges.begin(), edges.end()),5223 is_directed) {}5224 value(int n, const std::initializer_list<std::pair<int, int>> &edges,5225 bool is_directed = false)5226 : value(n, std::vector<std::pair<int, int>>(edges), is_directed) {}52275228 // Creates graph from tree (undirected, same edges).5229 // O(n).5230 value(const typename wtree<VWeight, EWeight>::value &t)5231 : value(t.n(), t.edges(), false) {5232 if (t.vertex_weights().has_value()) {5233 vertex_weights_ = *t.vertex_weights();5234 }5235 if (t.edge_weights().has_value()) {5236 edge_weights_ = *t.edge_weights();5237 }5238 }52395240 // Weight type conversion.5241 // O(n + m).5242 template <typename NewVWeight, typename NewEWeight>5243 typename wgraph<NewVWeight, NewEWeight>::value5244 convert_weight_types() const {5245 tgen_ensure(!vertex_weights_.has_value() and5246 !edge_weights_.has_value(),5247 "wgraph: value: cannot convert weight type after "5248 "assigning weights");52495250 ensure_adj_built();5251 typename wgraph<NewVWeight, NewEWeight>::value new_graph(5252 adj_, is_directed_);5253 new_graph.is_directed_ = is_directed_;5254 new_graph.add_1_ = add_1_;5255 new_graph.print_nm_ = print_nm_;5256 return new_graph;5257 }52585259 // Fetches number of vertices.5260 int n() const { return n_; }52615262 // Fetches number of edges.5263 int m() const { return edges_.size(); }52645265 // Fetches if graph is directed;5266 bool is_directed() const { return is_directed_; }52675268 // Fetches a const ref. to adjacency list.5269 const std::vector<std::set<int>> &adj() const {5270 ensure_adj_built();5271 return adj_;5272 }52735274 // Fetches a const ref. to edge set.5275 const std::vector<std::pair<int, int>> &edges() const { return edges_; }52765277 // Fetches vertex weights.5278 const std::optional<std::vector<VWeight>> &vertex_weights() const {5279 return vertex_weights_;5280 }52815282 // Fetches edge weights.5283 const std::optional<std::vector<EWeight>> &edge_weights() const {5284 return edge_weights_;5285 }52865287 // Sets vertex weights.5288 // O(n + m).5289 template <typename NewVWeight = VWeight>5290 typename wgraph<NewVWeight, EWeight>::value set_vertex_weights(5291 const std::vector<NewVWeight> &vertex_weights) const {5292 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),5293 "wgraph: value: must give `n` vertex weights");52945295 auto new_graph = convert_weight_types<NewVWeight, EWeight>();5296 new_graph.vertex_weights_ = vertex_weights;5297 return new_graph;5298 }52995300 // Sets edge weights.5301 // O(n + m).5302 template <typename NewEWeight = EWeight>5303 typename wgraph<VWeight, NewEWeight>::value5304 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {5305 tgen_ensure(static_cast<int>(edge_weights.size()) == m(),5306 "wgraph: value: must give `m` edge weights");53075308 auto new_graph = convert_weight_types<VWeight, NewEWeight>();5309 new_graph.edge_weights_ = edge_weights;5310 return new_graph;5311 }53125313 // Enables edge-weighted mode before adding weighted edges5314 // incrementally. The graph must have no edges yet. O(1).5315 value &edge_weighted() {5316 tgen_ensure(m() == 0,5317 "wgraph: value: edge_weighted requires a graph with no "5318 "edges");5319 tgen_ensure(!edge_weights_.has_value(),5320 "wgraph: value: graph is already edge-weighted");53215322 edge_weights_ = std::vector<EWeight>();5323 return *this;5324 }53255326 // Adds 1 to vertex ids, for printing.5327 // O(1).5328 value &add_1() {5329 add_1_ = true;5330 return *this;5331 }53325333 // Prints `n m` on a new line before printing the edges.5334 // O(1).5335 value &print_nm() {5336 print_nm_ = true;5337 return *this;5338 }53395340 // Shuffles the graph's vertex labels (except those in `indices`,5341 // which keep their current label) and edge order. The change is5342 // applied eagerly to the underlying adjacency list, edge list,5343 // vertex weights and edge weights.5344 // O(n + m).5345 value &shuffle_except(std::set<int> indices) {5346 ensure_adj_built();5347 // Builds the relabeling: for each vertex `i`, `new_label[i]` is5348 // its new id. Vertices in `indices` keep their label; the others5349 // are permuted among themselves.5350 std::vector<int> new_label(n());5351 std::vector<int> shuffled;5352 for (int i = 0; i < n(); ++i) {5353 if (indices.count(i))5354 new_label[i] = i;5355 else5356 shuffled.push_back(i);5357 }5358 std::vector<int> targets = shuffled;5359 tgen::shuffle(targets.begin(), targets.end());5360 for (size_t k = 0; k < shuffled.size(); ++k)5361 new_label[shuffled[k]] = targets[k];53625363 // Rewrites adjacency list with new labels.5364 std::vector<std::set<int>> new_adj(n());5365 for (int u = 0; u < n(); ++u)5366 for (int v : adj_[u])5367 new_adj[new_label[u]].insert(new_label[v]);5368 adj_ = new_adj;53695370 // Rewrites edges with new labels (canonical undirected order).5371 for (auto &[u, v] : edges_) {5372 u = new_label[u];5373 v = new_label[v];5374 if (!is_directed_ and u > v)5375 std::swap(u, v);5376 }53775378 // Permutes vertex weights to match the new labels.5379 if (vertex_weights_.has_value()) {5380 std::vector<VWeight> new_vw(n());5381 for (int i = 0; i < n(); ++i)5382 new_vw[new_label[i]] = (*vertex_weights_)[i];5383 vertex_weights_ = new_vw;5384 }53855386 // Shuffles edge order, keeping edge weights aligned.53875388 std::vector<int> perm(edges_.size());5389 std::iota(perm.begin(), perm.end(), 0);5390 tgen::shuffle(perm.begin(), perm.end());53915392 std::vector<std::pair<int, int>> new_edges;5393 std::optional<std::vector<EWeight>> new_ew;5394 if (edge_weights_.has_value())5395 new_ew = std::vector<EWeight>();5396 for (int i : perm) {5397 new_edges.push_back(edges_[i]);5398 if (new_ew.has_value())5399 new_ew->push_back((*edge_weights_)[i]);5400 }54015402 edges_ = new_edges;5403 if (new_ew.has_value())5404 edge_weights_ = new_ew;54055406 return *this;5407 }54085409 // Shuffles the graph's vertices and edge order.5410 // O(n + m).5411 value &shuffle() { return shuffle_except({}); }54125413 // Adds `k` vertices to the graph (labeled n, n+1, ...n+k-1). Updates5414 // `n` accordingly.5415 // O(k) amortized.5416 value &add_vertices(int k, std::optional<std::vector<VWeight>>5417 new_vertex_weights = std::nullopt) {5418 ensure_adj_built();5419 n_ += k;5420 adj_.resize(n());5421 if (new_vertex_weights.has_value()) {5422 tgen_ensure(vertex_weights().has_value(),5423 "wgraph: value: cannot add weighted vertices to "5424 "vertex-unweighted graph");5425 tgen_ensure(5426 static_cast<int>(new_vertex_weights->size()) == k,5427 "wgraph: value: number of vertex weights must be equal "5428 "to number of added vertices");54295430 vertex_weights_->insert(vertex_weights_->end(),5431 new_vertex_weights->begin(),5432 new_vertex_weights->end());5433 } else5434 tgen_ensure(!vertex_weights().has_value(),5435 "wgraph: value: cannot add unweighted vertices to "5436 "vertex-weighted graph");54375438 return *this;5439 }54405441 // Adds edge (u, v).5442 // O(log n) amortized.5443 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {5444 ensure_adj_built();5445 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),5446 "wgraph: value: vertex ids must be valid");54475448 if (!is_directed() and u > v)5449 std::swap(u, v);54505451 if (adj_[u].count(v))5452 return *this;54535454 adj_[u].insert(v);5455 if (!is_directed())5456 adj_[v].insert(u);5457 edges_.emplace_back(u, v);54585459 if (w.has_value()) {5460 tgen_ensure(edge_weights().has_value(),5461 "wgraph: value: cannot add weighted edge to "5462 "edge-unweighted graph");54635464 edge_weights_->push_back(*w);5465 } else5466 tgen_ensure(!edge_weights().has_value(),5467 "wgraph: value: cannot add unweighted edge to "5468 "edge-weighted graph");54695470 return *this;5471 }54725473 // Links graph with another `rhs`, adding the edge between u (in left5474 // graph) and v (in right graph). Ids for added vertices are updated5475 // accordingly.5476 // O(rhs.n + rhs.m * log n) amortized.5477 value &link(const value &rhs, int new_u, int new_v,5478 std::optional<EWeight> new_w = std::nullopt) {5479 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and5480 new_v < rhs.n(),5481 "wgraph: value: vertex ids must be valid");54825483 // Edges from right-hand side.5484 int shift = n();5485 add_vertices(rhs.n(), rhs.vertex_weights());5486 for (int i = 0; i < rhs.m(); ++i) {5487 auto [u, v] = rhs.edges()[i];5488 add_edge(shift + u, shift + v,5489 rhs.edge_weights().has_value()5490 ? std::optional<EWeight>((*rhs.edge_weights())[i])5491 : std::nullopt);5492 }54935494 // New edge.5495 add_edge(new_u, shift + new_v, new_w);54965497 return *this;5498 }54995500 // Glues the graph with another `rhs` such that index_pairs[i].first is5501 // considered to be the same as index_pairs[i].second. Ids for added5502 // vertices are updated accordingly.5503 // O(rhs.n + rhs.m * log n) amortized.5504 value &glue(const value &rhs,5505 std::set<std::pair<int, int>> index_pairs) {5506 tgen_ensure(5507 is_directed() == rhs.is_directed(),5508 "wgraph: value: graphs must have the same is_directed value");55095510 // Checks validity of indices.5511 std::set<int> idx_left, idx_right;5512 std::vector<int> right_id_to_left(rhs.n(), -1);5513 for (auto [l, r] : index_pairs) {5514 tgen_ensure(5515 0 <= l and l < n() and 0 <= r and r < rhs.n(),5516 "wgraph: value: vertex indices to glue must be valid");5517 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,5518 "wgraph: value: must not have repeated indices "5519 "on the same side to glue");55205521 idx_left.insert(l);5522 idx_right.insert(r);5523 right_id_to_left[r] = l;5524 }55255526 // Computes new ids of right vertices.5527 std::vector<int> new_right_id(rhs.n(), -1);5528 int intersection_lt = 0;5529 std::optional<std::vector<VWeight>> rhs_vertex_weights;5530 for (int i = 0; i < rhs.n(); ++i) {5531 if (right_id_to_left[i] != -1) {5532 // Is in intersection.5533 ++intersection_lt;5534 new_right_id[i] = right_id_to_left[i];5535 } else {5536 // New id.5537 new_right_id[i] = n() + i - intersection_lt;5538 if (rhs.vertex_weights().has_value()) {5539 if (!rhs_vertex_weights.has_value())5540 rhs_vertex_weights = std::vector<VWeight>();5541 rhs_vertex_weights->push_back(5542 (*rhs.vertex_weights())[i]);5543 }5544 }5545 }55465547 // Adds new vertices and edges.5548 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);5549 for (int i = 0; i < rhs.m(); ++i) {5550 auto [u, v] = rhs.edges()[i];5551 add_edge(new_right_id[u], new_right_id[v],5552 rhs.edge_weights().has_value()5553 ? std::optional<EWeight>((*rhs.edge_weights())[i])5554 : std::nullopt);5555 }55565557 return *this;5558 }5559 value &glue(const value &rhs,5560 std::initializer_list<std::pair<int, int>> il) {5561 return glue(rhs, std::set<std::pair<int, int>>(il));5562 }55635564 // Glues the graph with another `rhs` at `indices`. That is, idx in5565 // `indices` are considered to be the same vertex. Ids for added5566 // vertices are updated accordingly.5567 // O(rhs.n + rhs.m * log n) amortized.5568 value &glue(const value &rhs, std::set<int> indices) {5569 std::set<std::pair<int, int>> index_pairs;5570 for (auto i : indices)5571 index_pairs.emplace(i, i);5572 return glue(rhs, index_pairs);5573 }5574 value &glue(const value &rhs, const std::initializer_list<int> &il) {5575 return glue(rhs, std::set<int>(il));5576 }55775578 // Disjoint union.5579 // Shifts ids from `rhs` graph by n().5580 // O(rhs.n + rhs.m * log n) amortized.5581 value &disjoint_union(const value &rhs) {5582 return glue(rhs, std::set<int>());5583 }55845585 // Computes uniformly random subgraph of graph with num_edges edges.5586 // O(n + m).5587 value &random_subgraph(int num_edges) {5588 tgen_ensure(5589 num_edges <= m(),5590 "wgraph: value: can choose at most `m` edges from graph");55915592 std::vector<std::pair<int, int>> new_edges;5593 std::optional<std::vector<EWeight>> new_edge_weights;55945595 int left = m();5596 for (int i = 0; i < m(); ++i) {5597 if (next(1, left--) <= num_edges) {5598 new_edges.push_back(edges()[i]);5599 if (edge_weights_.has_value()) {5600 if (!new_edge_weights.has_value())5601 new_edge_weights = std::vector<EWeight>();5602 new_edge_weights->push_back((*edge_weights())[i]);5603 }5604 --num_edges;5605 }5606 }56075608 edges_ = new_edges;5609 edge_weights_ = new_edge_weights;5610 rebuild_adj_from_edge_list();5611 return *this;5612 }56135614 // Computes a random (not uniform) subgraph with `num_edges` edges that5615 // keeps every connected component connected (does not increase the5616 // number of connected components).5617 // 1. Picks a spanning forest via randomized Prim.5618 // 2. Adds additional edges uniformly at random.5619 // O(n + m).5620 value &random_connected_subgraph(int num_edges) {5621 tgen_ensure(!is_directed_,5622 "wgraph: value: random_connected_subgraph is only for "5623 "undirected graphs");5624 tgen_ensure(5625 num_edges <= m(),5626 "wgraph: value: can choose at most `m` edges from graph");56275628 // Builds an incidence list: for each vertex, the (neighbor, edge5629 // index) pairs.5630 std::vector<std::vector<std::pair<int, int>>> incident(n());5631 for (int i = 0; i < m(); ++i) {5632 auto [u, v] = edges_[i];5633 incident[u].emplace_back(v, i);5634 incident[v].emplace_back(u, i);5635 }56365637 // Randomized Prim.5638 std::vector<bool> vis(n(), false);5639 std::vector<int> queue;5640 std::vector<bool> in_tree(m(), false);5641 int forest_edges = 0;56425643 for (int start = 0; start < n(); ++start) {5644 if (vis[start])5645 continue;5646 vis[start] = true;5647 queue.push_back(start);56485649 while (!queue.empty()) {5650 int i = tgen::next<int>(0, queue.size() - 1);5651 int u = queue[i];5652 std::swap(queue[i], queue.back());5653 queue.pop_back();56545655 for (auto [v, edge_idx] : incident[u]) {5656 if (!vis[v]) {5657 vis[v] = true;5658 queue.push_back(v);5659 in_tree[edge_idx] = true;5660 ++forest_edges;5661 }5662 }5663 }5664 }5665 tgen_ensure(5666 num_edges >= forest_edges,5667 "wgraph: value: random_connected_subgraph needs at least "5668 "`n - c` edges, where `c` is the number of connected "5669 "components");56705671 // Splits edge indices into forest edges and the rest.5672 std::vector<int> tree_idx, rest_idx;5673 for (int i = 0; i < m(); ++i) {5674 if (in_tree[i])5675 tree_idx.push_back(i);5676 else5677 rest_idx.push_back(i);5678 }56795680 tgen::shuffle(rest_idx.begin(), rest_idx.end());56815682 std::vector<int> chosen_idx;5683 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),5684 tree_idx.end());5685 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),5686 rest_idx.begin() + num_edges - forest_edges);56875688 detail::tgen_ensure_against_bug(5689 static_cast<int>(chosen_idx.size()) == num_edges,5690 "wgraph: value: chose a wrong number of edges");56915692 std::vector<std::pair<int, int>> new_edges;5693 std::optional<std::vector<EWeight>> new_edge_weights;5694 if (edge_weights_.has_value())5695 new_edge_weights = std::vector<EWeight>();5696 for (int i : chosen_idx) {5697 new_edges.push_back(edges_[i]);5698 if (new_edge_weights.has_value())5699 new_edge_weights->push_back((*edge_weights_)[i]);5700 }57015702 edges_ = new_edges;5703 edge_weights_ = new_edge_weights;5704 rebuild_adj_from_edge_list();5705 return *this;5706 }57075708 // Complement. Self loops are maintained.5709 // O(n^2).5710 value operator!() const {5711 tgen_ensure(!edge_weights_.has_value(),5712 "wgraph: value: cannot compute complement of "5713 "edge-weighted graph");57145715 value complement = *this;5716 complement.ensure_adj_built();5717 std::vector<std::pair<int, int>> compl_edges;5718 for (int i = 0; i < complement.n_; ++i) {5719 std::set<int> complement_adj;5720 for (int j = 0; j < complement.n_; ++j) {5721 bool add_j = false;5722 if (j == i and complement.adj_[i].count(j))5723 add_j = true;5724 if (j != i and !complement.adj_[i].count(j))5725 add_j = true;57265727 if (add_j) {5728 complement_adj.insert(j);5729 // If i > j and !is_directed(), we don't add the edge.5730 if (i <= j or complement.is_directed_) {5731 compl_edges.emplace_back(i, j);5732 }5733 }5734 }5735 std::swap(complement.adj_[i], complement_adj);5736 }5737 std::swap(complement.edges_, compl_edges);57385739 return complement;5740 }57415742 // Concatenates two values.5743 // O(N + M log N), N = n + rhs.n, M = m + rhs.m.5744 value operator+(const value &rhs) const {5745 tgen_ensure(is_directed() == rhs.is_directed(),5746 "wgraph: value: graphs must have the same "5747 "is_directed value");57485749 tgen_ensure(vertex_weights().has_value() ==5750 rhs.vertex_weights().has_value(),5751 "wgraph: value: cannot concatenate vertex-weighted "5752 "wgraph to unweighted");5753 tgen_ensure(edge_weights().has_value() ==5754 rhs.edge_weights().has_value(),5755 "wgraph: value: cannot concatenate edge-weighted "5756 "wgraph to unweighted");57575758 value concat = *this;5759 concat.glue(rhs, std::set<std::pair<int, int>>());5760 concat.add_1_ = add_1_ | rhs.add_1_;5761 concat.print_nm_ = print_nm_ | rhs.print_nm_;57625763 return concat;5764 }57655766 // Prints to std::ostream.5767 // O(n + m).5768 friend std::ostream &operator<<(std::ostream &out, const value &val) {5769 // Prints `n` and `m`.5770 if (val.print_nm_)5771 out << val.n() << " " << val.m() << '\n';57725773 // Prints vertex weights.5774 if (val.vertex_weights()) {5775 for (int i = 0; i < val.n(); ++i) {5776 if (i > 0)5777 out << " ";5778 out << (*val.vertex_weights())[i];5779 }5780 out << '\n';5781 }57825783 // Prints edges.5784 for (int i = 0; i < val.m(); ++i) {5785 auto [u, v] = val.edges()[i];5786 out << (u + val.add_1_) << " " << (v + val.add_1_);57875788 // Edge weight.5789 if (val.edge_weights().has_value())5790 out << " " << (*val.edge_weights())[i];57915792 out << '\n';5793 }57945795 return out;5796 }57975798 // Gets a std::tuple<n, m, adj> representing the value.5799 std::tuple<int, int, std::vector<std::set<int>>> to_std() const {5800 ensure_adj_built();5801 return std_type(n_, m(), adj_);5802 }58035804 private:5805 // Rebuilds adjacency from edges_ after replacing the edge list (e.g.5806 // subgraph operations).5807 // O(m log n).5808 void rebuild_adj_from_edge_list() {5809 adj_.assign(n_, {});5810 for (auto [u, v] : edges_) {5811 adj_[u].insert(v);5812 if (!is_directed_)5813 adj_[v].insert(u);5814 }5815 adj_built_ = true;5816 }58175818 // Builds adj_ from edges_ on first use.5819 // O(1) if already built; O(m log n) otherwise.5820 void ensure_adj_built() const {5821 if (adj_built_)5822 return;5823 const_cast<value *>(this)->rebuild_adj_from_edge_list();5824 }5825 };58265827 // Adds all edges from `rhs` as preset edges.5828 // O(rhs.m * log m).5829 wgraph &add_edges_from(const value &rhs) {5830 tgen_ensure(is_directed_ == rhs.is_directed(),5831 "wgraph: graphs must have the same is_directed value");58325833 for (auto [u, v] : rhs.edges())5834 add_edge(u, v);5835 return *this;5836 }58375838 // Generates graph value.5839 // Optimized for performance: dense no-preset graphs use index sampling;5840 // otherwise gen_remaining_edges.5841 // O(n + m log^2 n) expected.5842 value gen() const {5843 detail::tgen_ensure_against_bug(static_cast<int>(edges_.size()) <= m_,5844 "wgraph: too many edges were added");58455846 // All edges already added.5847 if (static_cast<int>(edges_.size()) == m_)5848 return value(n_, edges_, is_directed_);58495850 // Splits into two cases to optimize performance.58515852 // No presets and m > max_edges / 2: sample m distinct edge indices.5853 if (auto indexed = try_gen_by_edge_index())5854 return *indexed;58555856 // Otherwise: fill preset edges up to m_ with uniform random edges.5857 return gen_remaining_edges(5858 std::vector<std::pair<int, int>>(edges_.begin(), edges_.end()));5859 }58605861 // Gets a (not uniformly) random connected undirected graph.5862 // 1. Preset edges induce a spanning forest on their components.5863 // 2. Then, uniformly random edges between components are added.5864 // 3. Remaining edges are added uniformly at random.5865 // O(n + m log^2 n) expected.5866 value get_connected() const {5867 tgen_ensure(!is_directed_,5868 "wgraph: get_connected is only for undirected graphs");5869 tgen_ensure(m_ >= n_ - 1,5870 "wgraph: connected graph needs at least n - 1 edges");58715872 std::vector<std::pair<int, int>> edges;5873 edges.reserve(m_);58745875 if (edges_.empty()) {5876 if (n_ > 1) {5877 std::vector<int> prufer(n_ - 2);5878 for (int i = 0; i < n_ - 2; ++i)5879 prufer[i] = next<int>(0, n_ - 1);5880 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer)))5881 edges.emplace_back(u, v);5882 }5883 } else {5884 edges.assign(edges_.begin(), edges_.end());58855886 std::vector<std::vector<int>> adj(n_);5887 for (auto [u, v] : edges_) {5888 adj[u].push_back(v);5889 adj[v].push_back(u);5890 }58915892 std::vector<int> comp_size;5893 std::vector<std::vector<int>> component_ids;5894 std::vector<bool> vis(n_, false);5895 std::queue<int> q;58965897 for (int i = 0; i < n_; ++i) {5898 if (vis[i])5899 continue;59005901 vis[i] = true;5902 q.push(i);5903 comp_size.push_back(0);5904 component_ids.emplace_back();5905 while (q.size()) {5906 int u = q.front();5907 q.pop();5908 ++comp_size.back();5909 component_ids.back().push_back(u);5910 for (int v : adj[u]) {5911 if (!vis[v]) {5912 vis[v] = true;5913 q.push(v);5914 }5915 }5916 }5917 }59185919 if (component_ids.size() > 1) {5920 std::vector<int> prufer_values =5921 many_by_distribution(component_ids.size() - 2, comp_size);5922 for (auto [u, v] :5923 detail::edges_from_prufer(std::move(prufer_values)))5924 edges.emplace_back(pick(component_ids[u]),5925 pick(component_ids[v]));5926 }5927 }59285929 return gen_remaining_edges(std::move(edges));5930 }59315932 // Gets a (not uniformly) random directed acyclic graph.5933 // 1. Randomized Kahn (uniform choice among indegree-0 vertices) yields a5934 // random topological order of the preset edges (which must be acyclic).5935 // 2. Extra edges are sampled randomly using the order.5936 // With no preset edges: sample a random graph then orient acyclically.5937 // Optimized for performance (distinct upper-triangle edge-index sampling;5938 // rejection instead of pair::distinct for preset edges).5939 // O(n + m log^2 n) expected.5940 value get_acyclic() const {5941 tgen_ensure(is_directed_,5942 "wgraph: get_acyclic is only for directed graphs");59435944 if (edges_.empty()) {5945 std::vector<int> order(n_);5946 std::iota(order.begin(), order.end(), 0);5947 for (int i = n_ - 1; i > 0; --i)5948 std::swap(order[i], order[next(0, i)]);59495950 const long long max_pairs =5951 static_cast<long long>(n_) * (n_ - 1) / 2;5952 tgen_ensure(m_ <= max_pairs,5953 "wgraph: not enough edges to generate");59545955 std::vector<std::pair<int, int>> edges;5956 edges.reserve(m_);5957 for (long long idx : distinct_range<long long>(0, max_pairs - 1)5958 .gen_list(m_)5959 .to_std()) {5960 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);5961 edges.emplace_back(order[i], order[j]);5962 }5963 return value(n_, edges, true);5964 }59655966 std::vector<std::vector<int>> adj(n_);5967 std::vector<int> indeg(n_, 0);5968 for (auto [u, v] : edges_) {5969 adj[u].push_back(v);5970 ++indeg[v];5971 }59725973 std::vector<int> available;5974 for (int i = 0; i < n_; ++i)5975 if (indeg[i] == 0)5976 available.push_back(i);59775978 // Random topological order using randomized Kahn's algorithm.5979 std::vector<int> order;5980 while (!available.empty()) {5981 int idx = next(0, static_cast<int>(available.size()) - 1);5982 int u = available[idx];5983 std::swap(available[idx], available.back());5984 available.pop_back();59855986 order.push_back(u);5987 for (int v : adj[u])5988 if (--indeg[v] == 0)5989 available.push_back(v);5990 }59915992 tgen_ensure(static_cast<int>(order.size()) == n_,5993 "wgraph: preset edges contain a directed cycle");59945995 value acyclic(n_, edges_, true);59965997 // Generates final edges.59985999 detail::tgen_ensure_against_bug(acyclic.m() <= m_,6000 "wgraph: too many edges were added");60016002 if (acyclic.m() < m_) {6003 std::vector<int> order_pos(n_);6004 for (int i = 0; i < n_; ++i)6005 order_pos[order[i]] = i;60066007 std::unordered_set<uint64_t> seen;6008 seen.reserve(m_ * 2);6009 for (auto [u, v] : acyclic.edges())6010 seen.insert(6011 detail::undirected_edge_key(order_pos[u], order_pos[v]));60126013 const long long max_pairs =6014 static_cast<long long>(n_) * (n_ - 1) / 2;6015 while (acyclic.m() < m_) {6016 std::pair<int, int> edge;6017 if (!detail::try_generate_distinct(seen, [&] {6018 long long idx = next<long long>(0, max_pairs - 1);6019 edge = detail::decode_undirected_simple_edge(n_, idx);6020 return detail::undirected_edge_key(edge.first,6021 edge.second);6022 }))6023 throw detail::error("wgraph: not enough edges to generate");6024 acyclic.add_edge(order[edge.first], order[edge.second]);6025 }6026 }60276028 return acyclic;6029 }60306031 // Generates a (not uniformly) random skewed connected graph.6032 // 1. Builds the same skewed labeled tree as wtree::gen_skewed(n,6033 // elongation)(root 0, parent(i) = wnext(i, elongation) for i >= 1).6034 // If is_directed, tree edges are oriented down the tree.6035 // 2. Adds the remaining edges: pick an endpoint u uniformly;6036 // pick k uniformly in [1, spread]; walk from u toward the root k6037 // times along tree parents to get v; add edge (v, u).6038 // If elongation is small, generates a graph with small diameter.6039 // If elongation is large, generates a graph with large diameter, with6040 // vertices 0 and n-1 being far apart.6041 // O(n + m log n) if spread is O(1);6042 // O(n log n + m log^2 n) expected otherwise.6043 static value gen_skewed(int n, int m, int elongation, int spread,6044 bool is_directed = false) {6045 tgen_ensure(6046 m >= n - 1,6047 "wgraph: skewed graph needs at least n - 1 edges to be connected");6048 tgen_ensure(spread >= 2,6049 "wgraph: gen_skewed spread must be at least 2");60506051 value skewed(n, {}, is_directed);60526053 std::vector<int> parent(n), depth(n, 0);6054 parent[0] = 0;6055 for (int i = 1; i < n; ++i) {6056 int p = wnext<int>(i, elongation);6057 parent[i] = p;6058 depth[i] = depth[p] + 1;6059 skewed.add_edge(p, i);6060 }60616062 const int extra = m - (n - 1);6063 if (extra == 0)6064 return skewed;60656066 // If spread is large, use binary lifting to find the ancestor.6067 // Otherwise, enumerate O(n * spread) ancestor edges and sample6068 // directly.6069 constexpr int naive_ancestor_spread = 20;60706071 if (spread <= naive_ancestor_spread) {6072 std::vector<std::pair<int, int>> candidates;6073 candidates.reserve(n * spread);6074 for (int u = 0; u < n; ++u) {6075 int max_k = std::min(spread, depth[u]);6076 if (max_k < 2)6077 continue;6078 int v = parent[u];6079 for (int k = 2; k <= max_k; ++k) {6080 v = parent[v];6081 candidates.emplace_back(v, u);6082 }6083 }60846085 tgen_ensure(extra <= static_cast<int>(candidates.size()),6086 "wgraph: not enough edges to generate");60876088 for (auto [v, u] : choose(candidates, extra))6089 skewed.add_edge(v, u);6090 } else {6091 // Binary lifting.6092 int lg = 1;6093 while ((1 << lg) <= n)6094 ++lg;60956096 std::vector<std::vector<int>> up(lg, std::vector<int>(n));6097 for (int v = 0; v < n; ++v)6098 up[0][v] = parent[v];6099 for (int j = 1; j < lg; ++j)6100 for (int v = 0; v < n; ++v)6101 up[j][v] = up[j - 1][up[j - 1][v]];61026103 // Creates uniform generator of edges (u, v) such that v is ancestor6104 // of u. For that, every u has depth[u]-1 choices for v, so we6105 // weight u by min(spread - 1, depth[u] - 1). After that we can6106 // just pick the ancestor uniformly.6107 std::vector<int> distribution = depth;6108 for (int &d : distribution)6109 d = std::max(0, std::min(spread - 1, d - 1));6110 weighted_sampler vertex_choice(distribution);6111 distinct extra_edges([&]() -> std::pair<int, int> {6112 int u = vertex_choice.next();6113 int k = next(2, spread);6114 int v = u;6115 for (int j = 0; j < lg; ++j)6116 if (k >> j & 1)6117 v = up[j][v];6118 return {v, u};6119 });61206121 while (skewed.m() < m) {6122 std::pair<int, int> edge;6123 try {6124 edge = extra_edges.gen();6125 } catch (const std::runtime_error &e) {6126 if (std::string(e.what()) ==6127 "tgen: distinct: no more distinct values")6128 throw detail::error(6129 "wgraph: not enough edges to generate");6130 throw e;6131 }61326133 skewed.add_edge(edge.first, edge.second);6134 }6135 }61366137 return skewed;6138 }61396140 // Generates a random bipartite graph. The first side has vertices6141 // 0 .. n1-1, the second n1 .. n1+n2-1.6142 // Uniform when connected is false (distinct cross-edge indices).6143 // When connected, bipartite Prüfer + rejection fill; not uniform over6144 // connected bipartite graphs.6145 // O(n1 + n2 + m log(n1 * n2)) expected.6146 static value gen_bipartite(int n1, int n2, int m, bool connected = false) {6147 tgen_ensure(m >= 0, "wgraph: number of edges must be nonnegative");6148 long long num_edges = 1LL * n1 * n2;6149 tgen_ensure(m <= num_edges,6150 "wgraph: bipartite graph has at most n1 * n2 edges");6151 if (connected)6152 tgen_ensure(6153 m >= n1 + n2 - 1,6154 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "6155 "edges");61566157 if (!connected) {6158 std::vector<std::pair<int, int>> edges;6159 edges.reserve(m);6160 for (long long idx : distinct_range<long long>(0, num_edges - 1)6161 .gen_list(m)6162 .to_std())6163 edges.emplace_back(static_cast<int>(idx / n2),6164 n1 + static_cast<int>(idx % n2));6165 return value(n1 + n2, std::move(edges), false);6166 }61676168 std::unordered_set<uint64_t> used_edges;6169 used_edges.reserve(m * 2);6170 std::vector<std::pair<int, int>> edges;6171 edges.reserve(m);61726173 auto pack_edge = [](int u, int v) -> uint64_t {6174 if (u > v)6175 std::swap(u, v);6176 return (static_cast<uint64_t>(u) << 32) | static_cast<uint32_t>(v);6177 };61786179 if (n1 > 0 and n2 > 0) {6180 std::vector<int> prufer(n1 + n2 - 2);6181 for (int i = 0; i < n2 - 1; ++i)6182 prufer[i] = next(0, n1 - 1);6183 for (int i = 0; i < n1 - 1; ++i)6184 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);6185 shuffle(prufer.begin(), prufer.end());6186 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {6187 if (u > v)6188 std::swap(u, v);6189 if (used_edges.insert(pack_edge(u, v)).second)6190 edges.emplace_back(u, v);6191 }6192 detail::tgen_ensure_against_bug(6193 used_edges.size() == size_t(n1 + n2 - 1),6194 "wgraph: invalid bipartite spanning tree size");6195 }61966197 while (edges.size() < size_t(m)) {6198 int u = next(0, n1 - 1);6199 int v = next(n1, n1 + n2 - 1);6200 if (used_edges.insert(pack_edge(u, v)).second)6201 edges.emplace_back(u, v);6202 }62036204 return value(n1 + n2, std::move(edges), false);6205 }62066207 private:6208 // If this generator has no preset edges and m is large relative to the6209 // maximum edge count, sample by distinct edge index. Otherwise6210 // std::nullopt.6211 // Optimized for performance (index sampling instead of rejection).6212 // O(m log n).6213 std::optional<value> try_gen_by_edge_index() const {6214 if (!edges_.empty())6215 return std::nullopt;62166217 long long max_edges =6218 detail::max_graph_edges(n_, is_directed_, has_self_loops_);6219 if (m_ > max_edges)6220 throw detail::error("wgraph: not enough edges to generate");6221 if (max_edges <= 0 or 2LL * m_ <= max_edges)6222 return std::nullopt;62236224 std::vector<std::pair<int, int>> edges;6225 edges.reserve(m_);6226 for (long long idx :6227 distinct_range<long long>(0, max_edges - 1).gen_list(m_).to_std())6228 edges.push_back(detail::decode_graph_edge_index(6229 n_, idx, is_directed_, has_self_loops_));62306231 return value(n_, edges, is_directed_);6232 }62336234 // Fills `edges` up to m_ with uniform random edges not already present.6235 // Optimized for performance (uint64 edge keys + try_generate_distinct).6236 // O(m log^2 n) expected.6237 value gen_remaining_edges(std::vector<std::pair<int, int>> edges) const {6238 detail::tgen_ensure_against_bug(static_cast<int>(edges.size()) <= m_,6239 "wgraph: too many edges were added");62406241 if (static_cast<int>(edges.size()) == m_)6242 return value(n_, edges, is_directed_);62436244 edges.reserve(m_);62456246 std::unordered_set<uint64_t> seen;6247 seen.reserve(m_ * 2);6248 for (auto [u, v] : edges) {6249 if (!is_directed_ and u > v)6250 std::swap(u, v);6251 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)6252 : detail::undirected_edge_key(u, v));6253 }62546255 while (static_cast<int>(edges.size()) < m_) {6256 std::pair<int, int> edge;6257 if (!detail::try_generate_distinct(seen, [&] {6258 edge = detail::get_random_graph_edge(n_, is_directed_,6259 has_self_loops_);6260 if (!is_directed_ and edge.first > edge.second)6261 std::swap(edge.first, edge.second);6262 return is_directed_ ? detail::directed_edge_key(edge.first,6263 edge.second)6264 : detail::undirected_edge_key(6265 edge.first, edge.second);6266 }))6267 throw detail::error("wgraph: not enough edges to generate");6268 edges.emplace_back(edge);6269 }62706271 return value(n_, edges, is_directed_);6272 }6273};62746275// Implementation of wtree::value constructor from wgraph.6276// O(n + m alpha(n)).6277template <typename VWeight, typename EWeight>6278wtree<VWeight, EWeight>::value::value(6279 const typename wgraph<VWeight, EWeight>::value &g)6280 : n_(g.n()), adj_(g.n()), add_1_(false), print_n_(false), dsu_(g.n()) {6281 tgen_ensure(g.n() > 0, "wtree: value: graph must have at least one vertex");6282 tgen_ensure(!g.is_directed(),6283 "wtree: value: graph must be undirected to form a tree");62846285 if (g.vertex_weights().has_value())6286 vertex_weights_ = *g.vertex_weights();6287 if (g.edge_weights().has_value())6288 edge_weights_ = std::vector<EWeight>();62896290 if (n_ == 1)6291 return;62926293 std::vector<int> order(g.m());6294 std::iota(order.begin(), order.end(), 0);6295 tgen::shuffle(order.begin(), order.end());62966297 std::vector<std::pair<int, int>> tree_edges;6298 tree_edges.reserve(n_ - 1);62996300 for (int i : order) {6301 auto [u, v] = g.edges()[i];6302 if (!dsu_.unite(u, v))6303 continue;6304 if (u > v)6305 std::swap(u, v);63066307 tree_edges.emplace_back(u, v);6308 adj_[u].insert(v);6309 adj_[v].insert(u);6310 if (edge_weights_.has_value())6311 edge_weights_->push_back((*g.edge_weights())[i]);6312 if (static_cast<int>(tree_edges.size()) == n_ - 1)6313 break;6314 }63156316 tgen_ensure(static_cast<int>(tree_edges.size()) == n_ - 1,6317 "wtree: value: graph must be connected to form a tree");63186319 edges_ = std::move(tree_edges);6320}63216322/*6323 * Other types of weighted-ness.6324 */63256326// Vertex weighted graph.6327template <typename VWeight> using vgraph = wgraph<VWeight, int>;63286329// Edge weighted graph.6330template <typename EWeight> using egraph = wgraph<int, EWeight>;63316332// Unweighted graph.6333using graph = wgraph<int, int>;63346335/*6336 * Standard graphs.6337 */63386339// Complete.6340// O(n^2).6341inline graph::value K(int n) { return graph(n, n * (n - 1) / 2).gen(); }63426343// Path.6344// Path with `n` vertices. The edges of the path are 0 and n-1.6345// If directed, edges are i -> i+1 for i in [0, n-2).6346// O(n).6347inline graph::value P(int n, bool is_directed = false) {6348 graph g(n, n - 1, is_directed);6349 for (int i = 0; i + 1 < n; ++i)6350 g.add_edge(i, i + 1);6351 return g.gen();6352}63536354// Cycle.6355// n >= 3.6356// If directed, edges are i -> (i+1) % n.6357// O(n).6358inline graph::value C(int n, bool is_directed = false) {6359 tgen_ensure(n >= 3, "graph: cycle size must be at least 3");63606361 graph g(n, n, is_directed);6362 for (int i = 0; i < n; ++i)6363 g.add_edge(i, (i + 1) % n);6364 return g.gen();6365}63666367// Complete bipartite.6368// The first side has vertices `0` to `n1-1`, the second side has vertices `n1`6369// to `n1+n2-1`.6370// O(n1 * n2).6371inline graph::value K(int n1, int n2) {6372 graph g(n1 + n2, static_cast<long long>(n1) * n2);6373 for (int i = 0; i < n1; ++i)6374 for (int j = 0; j < n2; ++j)6375 g.add_edge(i, n1 + j);6376 return g.gen();6377}63786379// Star.6380// The center is vertex 0.6381// O(n).6382inline graph::value S(int n) { return K(1, n - 1); }63836384/****************6385 * *6386 * GEOMETRY *6387 * *6388 ****************/63896390namespace geometry {63916392// Point on the plane with coordinates of type T.6393template <typename T> struct point {6394 static_assert(std::is_arithmetic_v<T>,6395 "point requires an arithmetic coordinate type");63966397 // Dot/cross product type: __int128 for T = long long, long long for other6398 // integral T, T for floating-point.6399 using product_t = std::conditional_t<6400 std::is_same_v<T, long long>, detail::i128,6401 std::conditional_t<std::is_integral_v<T>, long long, T>>;64026403 // x and y coordinates.6404 T x_, y_;64056406 // Constructs a point with coordinates x and y.6407 point(T x = 0, T y = 0) : x_(x), y_(y) {}64086409 // Returns the x coordinate.6410 T x() const { return x_; }64116412 // Returns the y coordinate.6413 T y() const { return y_; }64146415 // Equality of coordinates, with epsilon-based equality for floating-point6416 // coordinates (tolerance 1e-9).6417 static bool coord_eq(T a, T b) {6418 if constexpr (std::is_integral_v<T>)6419 return a == b;6420 constexpr T eps = T(1e-9);6421 T d = a - b;6422 return d >= -eps and d <= eps;6423 }64246425 // Lexicographic order (by x, then y).6426 bool operator<(const point &p) const {6427 if (!coord_eq(x_, p.x()))6428 return x_ < p.x();6429 return y_ < p.y();6430 }64316432 // Equality of coordinates.6433 bool operator==(const point &p) const {6434 return coord_eq(x_, p.x()) and coord_eq(y_, p.y());6435 }64366437 // Vector addition.6438 point operator+(const point &p) const {6439 return point(x_ + p.x(), y_ + p.y());6440 }64416442 // Vector subtraction.6443 point operator-(const point &p) const {6444 return point(x_ - p.x(), y_ - p.y());6445 }64466447 // Scalar multiplication.6448 point operator*(T c) const { return point(x_ * c, y_ * c); }64496450 // Dot product.6451 product_t operator*(const point &p) const {6452 if constexpr (std::is_floating_point_v<T>)6453 return x_ * p.x() + y_ * p.y();6454 return product_t(x_) * p.x() + product_t(y_) * p.y();6455 }64566457 // Cross product (signed area of the parallelogram).6458 product_t operator^(const point &p) const {6459 if constexpr (std::is_floating_point_v<T>)6460 return x_ * p.y() - y_ * p.x();6461 return product_t(x_) * p.y() - product_t(y_) * p.x();6462 }64636464 // Prints the point as "x y".6465 friend std::ostream &operator<<(std::ostream &out, const point &p) {6466 return out << p.x() << ' ' << p.y();6467 }6468};64696470// Generates n distinct integer points in [min_coord, max_coord]^2 with no three6471// collinear.6472// O(n).6473inline std::vector<point<long long>>6474random_points_general_position(int n, long long min_coord,6475 long long max_coord) {6476 tgen_ensure(n > 0,6477 "geometry: random_points_general_position: n must be positive");6478 tgen_ensure(max_coord >= min_coord,6479 "geometry: random_points_general_position: min_coord must be "6480 "at most max_coord");6481 tgen_ensure(6482 static_cast<detail::i128>(max_coord) - min_coord <=6483 std::numeric_limits<long long>::max(),6484 "geometry: random_points_general_position: coordinate range too large");6485 uint64_t width = max_coord - min_coord;6486 uint64_t p = math::prime_from(2 * n);64876488 // Requires width >= p - 1 because sheared coordinates lie in [0, p - 1].6489 tgen_ensure(width >= p - 1,6490 "geometry: random_points_general_position: coordinate range "6491 "too small for n");64926493 // Base set {(x, x^-1 mod p) : x \in {1, ..., p - 1}}.6494 //6495 // Over F_p, y = x^-1 is a rational map on nonzero x, so any line meets the6496 // graph in at most two points. Distinct x therefore give distinct points;6497 // no three of them can be collinear in the integer plane.6498 std::vector<uint64_t> x_range(p - 1);6499 std::iota(x_range.begin(), x_range.end(), 1);6500 shuffle(x_range.begin(), x_range.end());6501 std::vector<detail::i128> bx(n), by(n);6502 for (int i = 0; i < n; ++i) {6503 uint64_t x = x_range[i];6504 bx[i] = x;6505 by[i] = math::modular_inverse(x, p);6506 }65076508 // Applies a random element of SL(2, p) by composing several elementary6509 // shear matrices over F_p.6510 //6511 // Each step applies either6512 // [1 r] or [1 0]6513 // [0 1] [r 1]6514 //6515 // with r \in {-2, -1, 1, 2}, and all arithmetic performed modulo p.6516 // After all iterations, the resulting transformation is6517 // A = S_k S_{k-1} ... S_16518 //6519 // where every S_i has determinant 1. Therefore det(A) = 1 (mod p),6520 // so A is invertible.6521 //6522 // Invertible affine transformations of F_p^2 preserve collinearity and6523 // non-collinearity. Since the base set {(x, x^-1 mod p)} contains no6524 // three collinear points, the transformed set also contains no three6525 // collinear points.6526 const int num_shears = 8;6527 std::vector<detail::i128> lin_x = bx, lin_y = by;65286529 for (int it = 0; it < num_shears; ++it) {6530 bool vertical_shear = next(2) == 0;6531 int shear_r = pick({-2, -1, 1, 2});65326533 for (int i = 0; i < n; ++i) {6534 if (vertical_shear)6535 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;6536 else6537 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;65386539 if (lin_x[i] < 0)6540 lin_x[i] += p;6541 if (lin_y[i] < 0)6542 lin_y[i] += p;6543 }6544 }65456546 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],6547 max_y = lin_y[0];6548 for (int i = 1; i < n; ++i) {6549 min_x = std::min(min_x, lin_x[i]);6550 max_x = std::max(max_x, lin_x[i]);6551 min_y = std::min(min_y, lin_y[i]);6552 max_y = std::max(max_y, lin_y[i]);6553 }65546555 long long x_shift =6556 min_coord - min_x + next<long long>(0, width - (max_x - min_x));6557 long long y_shift =6558 min_coord - min_y + next<long long>(0, width - (max_y - min_y));65596560 std::vector<point<long long>> pts;6561 for (int i = 0; i < n; ++i)6562 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);6563 return pts;6564}65656566namespace detail {65676568using i128 = tgen::detail::i128;65696570// Signed area of triangle (a, b, p); positive iff (a, b, p) are in6571// counterclockwise order. 0 iff (a, b, p) are collinear. O(1).6572inline i128 ccw(const point<long long> &a, const point<long long> &b,6573 const point<long long> &p) {6574 return (static_cast<i128>(b.x()) - a.x()) *6575 (static_cast<i128>(p.y()) - a.y()) -6576 (static_cast<i128>(b.y()) - a.y()) *6577 (static_cast<i128>(p.x()) - a.x());6578}65796580// Integer projection of P onto line AB (A and B need not be distinct).6581inline i128 proj_on_ab(const point<long long> &P, const point<long long> &A,6582 const point<long long> &B) {6583 return (P - A) * (B - A);6584}65856586// In-place Hamiltonian path on points[left..right-1] with points[left]6587// start and points[right-1] end.6588// O(n log n) expected if points are "random", O(n^2) worst case.6589inline void conquer(std::vector<point<long long>> &points, int left,6590 int right) {6591 if (right - left <= 3)6592 return;65936594 point<long long> A = points[left], B = points[right - 1];65956596 // If all points are collinear, sort them properly and return.6597 bool all_collinear = true;6598 for (int k = left + 1; k < right - 1; ++k) {6599 if (ccw(A, B, points[k]) != 0) {6600 all_collinear = false;6601 break;6602 }6603 }6604 if (all_collinear) {6605 std::sort(points.begin() + left, points.begin() + right,6606 [&](const point<long long> &P, const point<long long> &Q) {6607 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);6608 });6609 return;6610 }66116612 // Choses a pivot that is not collinear with A and B.6613 std::vector<int> candidates;6614 for (int k = left + 1; k < right - 1; ++k) {6615 if (ccw(A, B, points[k]) != 0)6616 candidates.push_back(k);6617 }6618 int ci = candidates[next(0, static_cast<int>(candidates.size()) - 1)];6619 point<long long> C = points[ci];66206621 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());6622 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());6623 bool a_on_positive = ccw(C, A, B) < 0;66246625 // Classify interior points into two sides of the wedge A-C-B for partition.6626 // Collinear points on AB are tie-broken along the segment.6627 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);6628 auto is_positive = [&](const point<long long> &P) -> bool {6629 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);6630 // Weighted wedge side of P w.r.t. C, A, B.6631 if (s != 0)6632 return s > 0;6633 // P is on line AB: split by projection past the midpoint.6634 return 2 * proj_on_ab(P, A, B) > proj_sum;6635 };66366637 // Holds C at points[right-2] while classifying interior points in6638 // [left+1, right-3].6639 if (ci != right - 2)6640 std::swap(points[ci], points[right - 2]);66416642 int i = left + 1;6643 int j = right - 3;6644 while (i < j) {6645 if (is_positive(points[i]) == a_on_positive)6646 ++i;6647 else if (is_positive(points[j]) != a_on_positive)6648 --j;6649 else {6650 std::swap(points[i], points[j]);6651 ++i;6652 --j;6653 }6654 }66556656 // After partition:6657 // points[left]=A | (A,C)... | C | (C,B)... | points[right-1]=B.66586659 // After the swap, p is the index of C (pivot between the two subpaths).6660 int p = i;6661 if (i == j and is_positive(points[i]) == a_on_positive)6662 ++p;6663 std::swap(points[p], points[right - 2]);66646665 // Path A -> C.6666 conquer(points, left, p + 1);6667 // Path C -> B.6668 conquer(points, p, right);6669}66706671// Samples k sorted distinct integers from [left, right] uniformly.6672// Optimized for performance (pool partial Fisher–Yates or complement path for6673// modest ranges; sparse-map fallback otherwise).6674// O(k log k); O(right - left) memory when the range is modest.6675inline std::vector<long long>6676sample_sorted_distinct_in_range(int k, long long left, long long right) {6677 long long universe = right - left + 1;6678 std::vector<long long> res;6679 res.reserve(k);6680 if (k == 0)6681 return res;66826683 constexpr long long pool_threshold = 8'000'000;6684 constexpr long long pool_always_below = 500'000;66856686 if (universe <= pool_threshold and6687 (universe <= pool_always_below or k >= universe / 4)) {6688 size_t u = universe;6689 size_t ks = k;6690 std::vector<long long> pool(u);6691 std::iota(pool.begin(), pool.end(), left);6692 size_t m = ks <= u / 2 ? ks : u - ks;6693 for (size_t i = 0; i < m; ++i) {6694 size_t j = next<size_t>(i, u - 1);6695 std::swap(pool[i], pool[j]);6696 }6697 if (ks <= u / 2) {6698 res.assign(pool.begin(), pool.begin() + ks);6699 std::sort(res.begin(), res.end());6700 } else {6701 std::vector<char> excluded(u, 0);6702 for (size_t i = 0; i < m; ++i)6703 excluded[pool[i] - left] = 1;6704 for (long long v = left; v <= right; ++v)6705 if (!excluded[v - left])6706 res.push_back(v);6707 }6708 } else {6709 std::unordered_map<long long, long long> virtual_list;6710 virtual_list.reserve(k * 2);6711 for (long long i = 0; i < k; ++i) {6712 long long j = next<long long>(i, universe - 1);6713 long long vi = virtual_list.count(i) ? virtual_list[i] : i;6714 long long vj = virtual_list.count(j) ? virtual_list[j] : j;6715 virtual_list[j] = vi;6716 virtual_list[i] = vj;6717 res.push_back(virtual_list[i] + left);6718 }6719 std::sort(res.begin(), res.end());6720 }6721 return res;6722}67236724// Valtr-style signed edge components along one axis from n sorted distinct6725// coordinates. The n differences sum to zero.6726inline std::vector<long long>6727valtr_edge_components(const std::vector<long long> &sorted_coords) {6728 int n = sorted_coords.size();6729 std::vector<long long> left, right;6730 left.reserve(n / 2);6731 right.reserve(n / 2);6732 for (int i = 1; i + 1 < n; ++i) {6733 if (next(2) == 0)6734 left.push_back(sorted_coords[i]);6735 else6736 right.push_back(sorted_coords[i]);6737 }6738 long long lo = sorted_coords.front(), hi = sorted_coords.back();6739 std::vector<long long> seq;6740 seq.reserve(n + 1);6741 seq.push_back(lo);6742 for (long long v : left)6743 seq.push_back(v);6744 seq.push_back(hi);6745 for (auto it = right.rbegin(); it != right.rend(); ++it)6746 seq.push_back(*it);6747 seq.push_back(lo);6748 std::vector<long long> comps(n);6749 for (int i = 0; i < n; ++i)6750 comps[i] = seq[i + 1] - seq[i];6751 return comps;6752}67536754// Drops boundary vertices that are collinear with their cyclic neighbors.6755// O(m), m = |points|.6756inline std::vector<point<long long>>6757simplify_strict_boundary(std::vector<point<long long>> points) {6758 int n = points.size();6759 if (n < 3)6760 return points;67616762 std::vector<point<long long>> strict_points;6763 strict_points.reserve(n);6764 for (int i = 0; i < n; ++i) {6765 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)6766 strict_points.push_back(points[i]);6767 }6768 return strict_points;6769}67706771// Picks k evenly spaced vertices along a longer cyclic boundary.6772// O(k).6773inline std::vector<point<long long>>6774subsample_boundary(const std::vector<point<long long>> &points, int k) {6775 int n = points.size();6776 if (n <= k)6777 return points;67786779 std::vector<point<long long>> sampled_points;6780 sampled_points.reserve(k);6781 for (int i = 0; i < k; ++i)6782 sampled_points.push_back(points[(static_cast<i128>(i) * n) / k]);6783 return sampled_points;6784}67856786// Random translation so the polygon lies in the box.6787// O(|points|).6788inline void place_inside_box(std::vector<point<long long>> &points,6789 long long min_coord, long long max_coord) {6790 long long width = max_coord - min_coord + 1;67916792 i128 min_x = points[0].x(), max_x = points[0].x();6793 i128 min_y = points[0].y(), max_y = points[0].y();6794 for (const point<long long> &p : points) {6795 min_x = std::min(min_x, static_cast<i128>(p.x()));6796 max_x = std::max(max_x, static_cast<i128>(p.x()));6797 min_y = std::min(min_y, static_cast<i128>(p.y()));6798 max_y = std::max(max_y, static_cast<i128>(p.y()));6799 }68006801 i128 span_x = max_x - min_x;6802 i128 span_y = max_y - min_y;6803 // Random slack keeps the polygon inside the box without filling it.6804 i128 shift_x =6805 min_coord - min_x +6806 next<long long>(0, width - 1 - static_cast<long long>(span_x));6807 i128 shift_y =6808 min_coord - min_y +6809 next<long long>(0, width - 1 - static_cast<long long>(span_y));68106811 for (point<long long> &p : points)6812 p = point<long long>(p.x() + shift_x, p.y() + shift_y);6813}68146815// Random cyclic shift; Valtr walk is already counterclockwise.6816// O(|points|).6817inline void randomize_boundary_order(std::vector<point<long long>> &points) {6818 int rot = next(points.size());6819 if (rot > 0)6820 std::rotate(points.begin(), points.begin() + rot, points.end());6821}68226823// Valtr walk for m edges; bbox minimum translated to the origin.6824// O(m log m).6825inline std::vector<point<long long>>6826valtr_vertices(int m, const std::vector<long long> &x_comp,6827 std::vector<long long> y_comp) {6828 shuffle(y_comp.begin(), y_comp.end());68296830 std::vector<point<long long>> edges(m);6831 // Upper half-plane (positive y, or y = 0 and x > 0) sorts before lower.6832 auto upper = [](const point<long long> &p) {6833 return p.y() > 0 or (p.y() == 0 and p.x() > 0);6834 };6835 for (int i = 0; i < m; ++i)6836 edges[i] = point<long long>(x_comp[i], y_comp[i]);68376838 std::sort(edges.begin(), edges.end(),6839 [&upper](const point<long long> &a, const point<long long> &b) {6840 bool au = upper(a), bu = upper(b);6841 if (au != bu)6842 return au;6843 auto cross = a ^ b;6844 if (cross != 0)6845 return cross > 0;6846 return (a * a) < (b * b);6847 });68486849 // Prefix-sum the sorted edge vectors to obtain vertex coordinates.6850 i128 cur_x = 0, cur_y = 0;6851 std::vector<i128> px(m), py(m);6852 for (int i = 0; i < m; ++i) {6853 px[i] = cur_x;6854 py[i] = cur_y;6855 cur_x += edges[i].x();6856 cur_y += edges[i].y();6857 }6858 tgen::detail::tgen_ensure_against_bug(6859 cur_x == 0 and cur_y == 0,6860 "geometry: random_convex_polygon: walk did not close");68616862 i128 min_x = px[0], min_y = py[0];6863 for (int i = 1; i < m; ++i) {6864 min_x = std::min(min_x, px[i]);6865 min_y = std::min(min_y, py[i]);6866 }68676868 // Shift so the bbox minimum is at the origin.6869 std::vector<point<long long>> points;6870 points.reserve(m);6871 for (int i = 0; i < m; ++i)6872 points.emplace_back(px[i] - min_x, py[i] - min_y);6873 return points;6874}68756876} // namespace detail68776878// Generates n vertices of a convex integer polygon inside a box.6879// If strict is true, boundary vertices are guaranteed non-collinear when6880// generation succeeds; retry count depends on n and width.6881// Always returns points in counterclockwise order.6882// O(n log n).6883inline std::vector<point<long long>>6884random_convex_polygon(int n, long long min_coord, long long max_coord,6885 bool strict = false) {6886 tgen_ensure(n >= 3,6887 "geometry: random_convex_polygon: n must be at least 3");6888 tgen_ensure(max_coord >= min_coord,6889 "geometry: random_convex_polygon: min_coord must be at most "6890 "max_coord");6891 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=6892 std::numeric_limits<long long>::max(),6893 "geometry: random_convex_polygon: coordinate range too large");6894 long long width = max_coord - min_coord + 1;6895 tgen_ensure(6896 width >= n,6897 "geometry: random_convex_polygon: coordinate range too small for n");68986899 // Valtr walk size: n in weak mode; strict mode uses a larger grid so6900 // collinear removal still leaves at least n vertices to subsample.6901 int num_coords = n;6902 if (strict) {6903 // Extra grid lines beyond n: at least 100 (small-n headroom), about6904 // n/1000 for large n, and never more than width - n.6905 int extra = width <= n ? 06906 : std::min<long long>(std::max(100, n / 1000),6907 width - n);6908 num_coords = n + extra;6909 }69106911 // Strict mode retries coordinate sampling when simplification leaves < n6912 // vertices; weak mode has no failure path, so one attempt always suffices.6913 const int max_attempts = strict ? 32 : 1;6914 for (int i = 0; i < max_attempts; ++i) {6915 // Build a convex lattice polygon on [0, width - 1]^2, then translate.6916 std::vector<long long> x_sorted =6917 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);6918 std::vector<long long> y_sorted =6919 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);6920 std::vector<long long> x_comp = detail::valtr_edge_components(x_sorted);6921 std::vector<long long> y_comp = detail::valtr_edge_components(y_sorted);69226923 std::vector<point<long long>> points =6924 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));69256926 if (strict) {6927 std::vector<point<long long>> simplified =6928 detail::simplify_strict_boundary(std::move(points));6929 // Tight boxes can leave too few vertices -> resample coordinates.6930 if (static_cast<int>(simplified.size()) < n)6931 continue;69326933 points = detail::subsample_boundary(simplified, n);6934 }69356936 detail::place_inside_box(points, min_coord, max_coord);6937 detail::randomize_boundary_order(points);6938 return points;6939 }69406941 // Generation failed.6942 throw tgen::detail::error(6943 "geometry: random_convex_polygon: generation failed: coordinate "6944 "range too small for n");6945}69466947// Random simple polygon through given distinct points.6948// Collinear triples are allowed; fails if all points are collinear.6949// O(n log n) expected if points are "random", O(n^2) worst case.6950inline std::vector<point<long long>> random_simple_polygon_through_points(6951 const std::vector<point<long long>> &points) {6952 int n = points.size();6953 tgen_ensure(n >= 3,6954 "geometry: random_simple_polygon_through_points: need at "6955 "least 3 points");6956 tgen_ensure(6957 static_cast<int>(6958 std::set<point<long long>>(points.begin(), points.end()).size()) ==6959 n,6960 "geometry: random_simple_polygon_through_points: points must "6961 "be distinct");69626963 int idx_a = 0, idx_b = 0;6964 for (int i = 1; i < n; ++i) {6965 if (points[i] < points[idx_a])6966 idx_a = i;6967 if (points[idx_b] < points[i])6968 idx_b = i;6969 }6970 point<long long> A = points[idx_a], B = points[idx_b];69716972 bool all_collinear = true;6973 for (int i = 0; i < n; ++i) {6974 if (i == idx_a or i == idx_b)6975 continue;6976 if (detail::ccw(A, B, points[i]) != 0) {6977 all_collinear = false;6978 break;6979 }6980 }6981 tgen_ensure(!all_collinear,6982 "geometry: random_simple_polygon_through_points: all points "6983 "are collinear; no simple polygon exists");69846985 std::vector<point<long long>> chain;6986 chain.push_back(A);6987 int left_count = 0;6988 for (int i = 0; i < n; ++i) {6989 if (i == idx_a or i == idx_b)6990 continue;6991 if (detail::ccw(A, B, points[i]) > 0) {6992 chain.push_back(points[i]);6993 ++left_count;6994 }6995 }6996 chain.push_back(B);6997 for (int i = 0; i < n; ++i) {6998 if (i == idx_a or i == idx_b)6999 continue;7000 if (detail::ccw(A, B, points[i]) <= 0)7001 chain.push_back(points[i]);7002 }7003 chain.push_back(A);70047005 int n1 = 2 + left_count;7006 // Upper chain: A -> B.7007 detail::conquer(chain, 0, n1);7008 // Lower chain: B -> A.7009 detail::conquer(chain, n1 - 1, chain.size());70107011 // Cyclic vertex order: chain[1..n1) then chain[n1..end) (skip each path's7012 // start vertex).7013 std::vector<point<long long>> poly;7014 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);7015 poly.insert(poly.end(), chain.begin() + n1, chain.end());7016 return poly;7017}70187019namespace detail {70207021// Samples n distinct integer points in [min_coord, max_coord]^2.7022// O(n log n).7023inline std::vector<point<long long>>7024random_distinct_points_in_box(int n, long long min_coord, long long max_coord) {7025 long long width = max_coord - min_coord;7026 i128 side_128 = width + 1;7027 i128 universe = side_128 * side_128;7028 tgen_ensure(universe <= std::numeric_limits<long long>::max(),7029 "geometry: random_simple_polygon: coordinate range too large");7030 long long side = side_128;7031 tgen_ensure(universe >= n,7032 "geometry: random_simple_polygon: coordinate range too small "7033 "for n distinct points");70347035 // Decodes a linear grid key (x * side + y) to a point.7036 auto decode = [&](long long key) -> point<long long> {7037 return point<long long>(min_coord + key / side, min_coord + key % side);7038 };70397040 // Repeats until all generated points are not collinear.7041 // Runs O(1) times expected.7042 while (true) {7043 std::vector<long long> keys =7044 distinct_range<long long>(0, universe - 1).gen_list(n).to_std();70457046 std::vector<point<long long>> points;7047 points.reserve(n);7048 for (long long key : keys)7049 points.push_back(decode(key));70507051 // Checks if the points are not all collinear.7052 for (int i = 2; i < n; ++i) {7053 if (ccw(points[0], points[1], points[i]) != 0)7054 return points;7055 }7056 }7057}70587059} // namespace detail70607061// Random simple polygon.7062// If strict, vertex set has no three collinear points7063// (random_points_general_position); otherwise samples distinct grid points7064// (collinear triples allowed), so it might be the case that (polygon[i],7065// polygon[i+1], and polygon[i+2]) are collinear. Polygonizes via7066// random_simple_polygon_through_points.7067// O(n log n) expected.7068inline std::vector<point<long long>>7069random_simple_polygon(int n, long long min_coord, long long max_coord,7070 bool strict = false) {7071 tgen_ensure(n >= 3,7072 "geometry: random_simple_polygon: n must be at least 3");7073 tgen_ensure(max_coord >= min_coord,7074 "geometry: random_simple_polygon: min_coord must be at most "7075 "max_coord");7076 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord <=7077 std::numeric_limits<long long>::max(),7078 "geometry: random_simple_polygon: coordinate range too large");70797080 std::vector<point<long long>> points =7081 strict ? random_points_general_position(n, min_coord, max_coord)7082 : detail::random_distinct_points_in_box(n, min_coord, max_coord);7083 return random_simple_polygon_through_points(points);7084}70857086} // namespace geometry70877088/************7089 * *7090 * HACK *7091 * *7092 ************/70937094namespace hack {70957096namespace detail {70977098using namespace tgen::detail;70997100// Computes polynomial hash of a string.7101// O(|s|).7102inline int hash_string(const std::string &s, int base, int mod) {7103 long long h = 0;7104 for (char c : s)7105 h = (h * base + c - 'a' + 1) % mod;7106 return h;7107}71087109// Estimates the length of the string to very likely have a collision.7110inline int estimate_length(int alphabet_size, int mod) {7111 // Magic constants.7112 double base_len = 2.5 * std::log(std::sqrt(mod));7113 double scale = std::log(alphabet_size) / std::log(2.0);7114 double adjusted = base_len / std::max(1.0, scale * 0.7);71157116 return static_cast<int>(std::ceil(adjusted));7117}71187119// Collides two strings to have the same polynomial hash.7120// O(sqrt(mod) log(mod)) with high probability.7121inline std::pair<std::string, std::string>7122birthday_attack(const std::vector<std::string> &alphabet, int base, int mod) {7123 tgen_ensure(0 < base and base < mod,7124 "birthday_attack: base must be in (0, mod)");7125 std::map<uint64_t, std::vector<int>> seen;7126 int length = estimate_length(alphabet.size(), mod);71277128 while (true) {7129 std::vector<int> seq(length);71307131 std::string s;71327133 for (int i = 0; i < length; ++i) {7134 seq[i] = next<int>(0, alphabet.size() - 1);7135 s += alphabet[seq[i]];7136 }71377138 int h = hash_string(s, base, mod);71397140 auto it = seen.find(h);7141 if (it != seen.end() and it->second != seq) {7142 std::string a, b;71437144 for (int x : it->second)7145 a += alphabet[x];7146 for (int x : seq)7147 b += alphabet[x];71487149 if (a != b)7150 return {a, b};7151 }71527153 seen[h] = seq;7154 }7155}71567157// Tried to find correct multipliers for unordered_map/set to force7158// collisions. O(1).7159inline std::set<long long> std_hash_multipliers() {7160 std::set<long long> multipliers = {85229};71617162 // Codeforces GCC GNU G++17 7.3.0 case.7163 bool codeforces_gcc_case = true;7164 if (cpp.version_ != 0 and cpp.version_ != 17)7165 codeforces_gcc_case = false;7166 if (compiler.kind_ != compiler_kind::unknown and7167 compiler.kind_ != compiler_kind::gcc)7168 codeforces_gcc_case = false;7169 if (compiler.major_ > 7)7170 codeforces_gcc_case = false;71717172 if (codeforces_gcc_case)7173 multipliers.insert(107897);71747175 return multipliers;7176}71777178} // namespace detail71797180// Fetches prefix of length n of the string "abacabadabacabae...".7181// O(n).7182inline std::string abacaba(int n) {7183 tgen_ensure(n > 0, "str: size must be positive");7184 std::string str = "a";7185 char c = 'a';7186 while (static_cast<int>(str.size()) < n) {7187 int prev_size = str.size();7188 str += ++c;7189 for (int j = 0; j < prev_size and static_cast<int>(str.size()) < n; ++j)7190 str += str[j];7191 }7192 return str;7193}71947195// Two strings that have same polynomial hash for any base, for7196// mod = power of 2 up to 2^64.7197// Thue–Morse.7198// O(1).7199inline std::pair<std::string, std::string> unsigned_polynomial_hash() {7200 std::string a, b;7201 int size = 1 << 10;7202 for (int i = 0; i < size; ++i) {7203 a += 'a' + math::detail::popcount(i) % 2;7204 b += 'a' + ('b' - a[i]);7205 }7206 return {a, b};7207}72087209// Collides two strings to have the same polynomial hash.7210// O(sqrt(mod) log(mod)) with high probability.7211// 0 < base < mod.7212inline std::pair<std::string, std::string> polynomial_hash(int alphabet_size,7213 int base, int mod) {7214 tgen_ensure(alphabet_size > 1,7215 "hack: polynomial_hash: alphabet size must be greater "7216 "than 1");7217 tgen_ensure(0 < base and base < mod,7218 "hack: polynomial_hash: base must be in (0, mod)");72197220 std::vector<std::string> alphabet(alphabet_size);7221 for (int i = 0; i < alphabet_size; ++i)7222 alphabet[i] = std::string(1, 'a' + i);7223 std::iota(alphabet.begin(), alphabet.end(), 'a');7224 return detail::birthday_attack(alphabet, base, mod);7225}72267227// Collides two strings to have the same polynomial hash for multiple bases7228// and mods (up to 2 pairs).7229// O(sqrt(mod) log^2 (mod)) with high probability,7230// with mod = max(mod_1, mod_2).7231inline std::pair<std::string, std::string>7232polynomial_hash(int alphabet_size, std::vector<int> bases,7233 std::vector<int> mods) {7234 tgen_ensure(bases.size() == mods.size(),7235 "hack: polynomial_hash: bases and mods must have the same "7236 "size");7237 tgen_ensure(bases.size() > 0,7238 "hack: polynomial_hash: must have at least one (base, mod) "7239 "pair");7240 tgen_ensure(bases.size() <= 2,7241 "hack: polynomial_hash: multi-hash hack only supported "7242 "for up to 2 (base, mod) pairs");72437244 std::vector<std::string> alphabet(alphabet_size);7245 for (int i = 0; i < alphabet_size; ++i)7246 alphabet[i] = std::string(1, 'a' + i);7247 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);7248 if (bases.size() == 1)7249 return {S1, T1};7250 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);7251}72527253// Returns a list of integers for unordered_map/set to force collisions.7254// O(size).7255inline std::vector<long long> std_unordered(int size) {7256 tgen_ensure(size > 0, "hack: std_unordered: size must be positive");7257 std::set<long long> multipliers = detail::std_hash_multipliers();7258 long long mult = 1;7259 std::set<long long>::iterator it = multipliers.begin();72607261 std::vector<long long> list;7262 while (static_cast<int>(list.size()) < size) {7263 list.push_back(mult * (*it));7264 ++it;7265 if (it == multipliers.end()) {7266 it = multipliers.begin();7267 ++mult;7268 }7269 }7270 return list;7271}72727273// Returns queries that force \Theta(q sqrt n) asymptotic7274// for Mo algorithm for offline range queries.7275// Forces \Theta(q sqrt n) pointer moves for any ordering.7276// O(n log n + q).7277inline std::vector<std::pair<int, int>> mo_worst_case(int n, int q) {7278 std::set<std::pair<int, int>> queries;72797280 // Adversarial case.7281 int sq = std::sqrt(n);7282 for (int i = 0; i < sq; ++i) {7283 for (int j = i; j < sq; ++j) {7284 if (i * sq < n and j * sq < n)7285 queries.emplace(i * sq, j * sq);7286 }7287 }72887289 // Push extra queries.7290 for (int i = 0; i < n; ++i)7291 if (queries.size() < size_t(q)) {7292 queries.emplace(0, i);7293 queries.emplace(i, i);7294 queries.emplace(i, n - 1);7295 }72967297 std::vector<std::pair<int, int>> pool(queries.begin(), queries.end());7298 while (pool.size() < size_t(q)) {7299 int l = next(0, n - 1);7300 pool.emplace_back(l, next(l, n - 1));7301 }73027303 return choose(shuffled(pool), q);7304}73057306// Returns list of strings that have a high cost to insert in a std::set.7307// Forces cost \Theta(size log(size)).7308// Generates: {b, ab, aab, aaab, ...}.7309// O(size log(size)).7310inline std::vector<std::string> string_set_worst_case(int size) {7311 std::vector<std::string> list;7312 int k = 0, left = size;7313 while (left > 0) {7314 int cur_size = std::min(left, k + 1);7315 left -= cur_size;73167317 char right_char = cur_size == k + 1 ? 'b' : 'c';7318 list.push_back(std::string(cur_size - 1, 'a') + right_char);73197320 ++k;7321 }7322 return tgen::shuffled(list);7323}73247325// Graph for Dijkstra implementations that relax with <= instead of <.7326// Unit-weight layered graph: 0 -> {1,2}, then disjoint7327// 2x2 gadgets (i,i+1) -> {i+2,i+3} for i = 1,3,5,... Many vertices share the7328// same dist from 0; with `d + w <= dist[j]` each pop re-relaxes the whole7329// frontier below it. m = 2(n - 2) edges.7330// O(n).7331inline egraph<int>::value non_strict_relaxation_dijkstra_bug(int n) {7332 tgen_ensure(7333 n >= 3,7334 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");73357336 egraph<int>::value g(n, {}, true);7337 g.edge_weighted();7338 g.add_edge(0, 1, 1);7339 g.add_edge(0, 2, 1);7340 for (int i = 1; i + 2 < n; i += 2) {7341 g.add_edge(i, i + 2, 1);7342 if (i + 3 < n)7343 g.add_edge(i, i + 3, 1);73447345 g.add_edge(i + 1, i + 2, 1);7346 if (i + 3 < n)7347 g.add_edge(i + 1, i + 3, 1);7348 }73497350 return g.shuffle_except({0});7351}73527353// Graph for Dijkstra implementations that do not skip stale heap entries7354// (`if (d > dist[i]) continue`).7355// Hub mid = n/2: star 0 -> 1..mid-1 (weights 1..mid-1), funnel i -> mid7356// (weights 1,3,5,...), then mid -> mid+1.. (weight 1).7357// Without a stale-heap check, mid and its in-neighbors are re-popped and7358// re-relax.7359// m = n + mid - 3 edges, mid = floor(n/2).7360// O(n).7361inline egraph<int>::value stale_heap_dijkstra_bug(int n) {7362 tgen_ensure(n >= 4,7363 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");73647365 int mid = n / 2;7366 egraph<int>::value g(n, {}, true);7367 g.edge_weighted();7368 for (int i = 1; i < mid; ++i)7369 g.add_edge(0, i, i);7370 for (int i = 1; i < mid; ++i)7371 g.add_edge(i, mid, 2 * (mid - i) - 1);7372 for (int i = mid + 1; i < n; ++i)7373 g.add_edge(mid, i, 1);73747375 return g.shuffle_except({0});7376}73777378// Worst-case for FIFO-SPFA.7379// Forces Omega(n^2) from vertex 0 (Theta(n*m), m = 2n - 3).7380// Upper chain ai -> a(i+1) weight 1; lower chain bi -> b(i+1) weight 0;7381// vertical ai -> bi weight 0; cross bi -> a(i+1) weight 1. Upper chain sets7382// loose dist first; cross edges from settled bi then improve a(i+1).7383// m = 2n - 3.7384// O(n).7385inline egraph<int>::value spfa(int n) {7386 tgen_ensure(n >= 2, "hack: spfa: n must be at least 2");7387 tgen_ensure(n % 2 == 0, "hack: spfa: n must be even");73887389 egraph<int>::value g(n, {}, true);7390 g.edge_weighted();73917392 const int k = n / 2;7393 for (int i = 0; i + 1 < k; ++i)7394 g.add_edge(i, i + 1, 1);7395 for (int i = 0; i + 1 < k; ++i)7396 g.add_edge(k + i, k + i + 1, 0);7397 for (int i = 0; i < k; ++i)7398 g.add_edge(i, k + i, 0);7399 for (int i = 0; i + 1 < k; ++i)7400 g.add_edge(k + i, i + 1, 1);74017402 return g.shuffle_except({0});7403}74047405// Zadeh (1972) anti-shortest-paths flow network for Edmonds-Karp and Dinitz.7406// Source is vertex 0; sink is vertex 4l + 2k + 1.7407// n = 4l + 2k + 2, m = 6l + 4k + k^2 - 4.7408// O(l + k^2).7409inline egraph<int>::value dinitz_worst_case(int k, int l) {7410 tgen_ensure(k >= 1, "hack: dinitz_worst_case: k must be at least 1");7411 tgen_ensure(l >= 1, "hack: dinitz_worst_case: l must be at least 1");74127413 const int p1 = 2 * l - 1;7414 const int p2 = 2 * l;7415 const int q1 = 2 * l + 1;7416 const int q2 = 2 * l + 2;7417 const int n = 4 * l + 2 * k + 2;74187419 const int flow_cap = k * k * l;7420 const int layer_cap = k * k;74217422 auto a = [&](int i) { return 2 * l + 3 + 2 * i; };7423 auto b = [&](int i) { return 2 * l + 4 + 2 * i; };7424 auto t = [&](int i) { return 4 * l + 2 * k + 1 - i; };74257426 egraph<int>::value g(n, {}, true);7427 g.edge_weighted();74287429 for (int i = 0; i + 1 < 2 * l - 1; ++i)7430 g.add_edge(i, i + 1, flow_cap);7431 for (int i = 0; i + 1 < 2 * l - 1; ++i)7432 g.add_edge(t(i + 1), t(i), flow_cap);74337434 for (int i = 0; i < 2 * l - 1; i += 2) {7435 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);7436 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);7437 }74387439 for (int i = 0; i < k; ++i) {7440 g.add_edge(p1, a(i), flow_cap);7441 g.add_edge(p2, b(i), flow_cap);7442 g.add_edge(a(i), q2, flow_cap);7443 g.add_edge(b(i), q1, flow_cap);7444 }74457446 for (int i = 0; i < k; ++i)7447 for (int j = 0; j < k; ++j)7448 g.add_edge(a(i), b(j), 1);74497450 return g;7451}74527453// Returns a mask of length 19938, with weights such that xor-ing with mt199377454// outputs yields 0.7455// O(1).7456template <typename T> std::vector<bool> mt19937_xor_hash() {7457 static_assert(std::is_same_v<T, int> or std::is_same_v<T, long long>,7458 "hack: mt19937_xor_hash: T must be int or long long");74597460 constexpr std::size_t deg = 19937;74617462 std::bitset<deg + 1> a, b, c;7463 b[deg] = c[deg] = 1;7464 std::size_t l = 0, shift = 1;7465 std::mt19937 rng32;7466 std::mt19937_64 rng64;7467 for (std::size_t n = 0; n < deg * 2; ++n) {7468 a >>= 1;7469 if constexpr (std::is_same_v<T, int>)7470 a[deg] = rng32() & 1;7471 else7472 a[deg] = rng64() & 1;74737474 if ((c & a).count() % 2 == 0) {7475 ++shift;7476 continue;7477 }74787479 std::bitset<deg + 1> oc = c;7480 c ^= (b >> shift);7481 if (2 * l <= n) {7482 l = n + 1 - l;7483 b = oc;7484 shift = 1;7485 } else {7486 ++shift;7487 }7488 }74897490 std::vector<bool> mask(deg + 1);7491 for (std::size_t i = 0; i <= deg; ++i)7492 mask[i] = c[i];7493 return mask;7494}74957496// Convex polygon that breaks naive rotating calipers for maximum vertex7497// distance (advances j while dist(i, next(j)) > dist(i, j) instead of using7498// ccw).7499// O(1).7500inline std::vector<geometry::point<double>>7501naive_rotating_calipers_max_dist_bug() {7502 return {7503 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},7504 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},7505 };7506}75077508namespace detail {75097510// Builds a hack block of order k (length fib(2k+1)).7511// O(fib(2k+1)).7512inline std::vector<int> segment_tree_beats_worst_case_block(int k) {7513 tgen_ensure(k >= 1,7514 "hack: segment_tree_beats_worst_case: k must be at least 1");75157516 std::vector<int> a(k + 1), b(k + 1);7517 std::vector<std::vector<int>> vf(k + 1), vg(k + 1);75187519 a[1] = b[1] = 1;7520 vf[1] = {1};7521 vg[1] = {1, 0};75227523 for (int i = 2; i <= k; ++i) {7524 b[i] = b[i - 1] + a[i - 1];7525 a[i] = b[i] + a[i - 1];7526 for (int x : vf[i - 1])7527 vf[i].push_back(x + a[i] + b[i]);7528 vf[i].push_back(a[i]);7529 for (int x : vg[i - 1])7530 vf[i].push_back(x + a[i]);7531 vg[i] = vf[i];7532 vg[i].push_back(0);7533 for (int x : vg[i - 1])7534 vg[i].push_back(x);7535 }75367537 vf[k].push_back(0);7538 return vf[k];7539}75407541// Appends one update round for the tiled array (offset (round * an) mod L).7542// O(fib(2k+1)).7543inline void7544segment_tree_beats_append_round(std::vector<std::vector<int>> &updates,7545 int block_len, int an, int bn, int n,7546 int round) {7547 const int off = (round * an) % block_len;7548 const int add_off = (off + block_len - bn) % block_len;7549 for (int k = 0; k < block_len; ++k) {7550 const int s = k * block_len * block_len;7551 const int sub_end = off + an;7552 if (sub_end <= block_len)7553 updates.push_back({1, s + off, s + sub_end, bn});7554 else {7555 updates.push_back({1, s + off, s + block_len, bn});7556 updates.push_back({1, s, s + (sub_end - block_len), bn});7557 }7558 const int add_end = add_off + bn;7559 if (add_end <= block_len)7560 updates.push_back({0, s + add_off, s + add_end, an});7561 else {7562 updates.push_back({0, s + add_off, s + block_len, an});7563 updates.push_back({0, s, s + (add_end - block_len), an});7564 }7565 }7566 updates.push_back({2, 0, n, an});7567 for (int k = 0; k < block_len; ++k) {7568 const int s = k * block_len * block_len;7569 updates.push_back({3, s + (off + an - 1) % block_len, 0});7570 }7571}75727573} // namespace detail75747575// Array and updates for worst case of segment tree beats.7576// O(fib(2k+1)^3 + q).7577inline std::pair<std::vector<int>, std::vector<std::vector<int>>>7578segment_tree_beats_worst_case(int k, int q) {7579 tgen_ensure(k >= 1,7580 "hack: segment_tree_beats_worst_case: k must be at least 1");7581 tgen_ensure(k <= 7, "hack: segment_tree_beats_worst_case: k too large");7582 tgen_ensure(q > 0,7583 "hack: segment_tree_beats_worst_case: q must be positive");75847585 const auto &fib = math::fibonacci();7586 const int block_len = fib[k * 2 + 1];7587 const int an = fib[k * 2];7588 const int bn = fib[k * 2 - 1];75897590 const int len = block_len;7591 const int total = len * len * len;75927593 std::vector<int> block = detail::segment_tree_beats_worst_case_block(k);7594 std::vector<int> arr(total, 0);7595 for (int x = 0; x < block_len; ++x) {7596 const int s = x * len * len;7597 for (int i = 0; i < block_len; ++i)7598 arr[s + i] = block[i];7599 }76007601 std::vector<std::vector<int>> updates;7602 updates.reserve(q);7603 const int n = total;7604 for (int round = 0; updates.size() < static_cast<std::size_t>(q); ++round) {7605 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,7606 round);7607 if (updates.size() > static_cast<std::size_t>(q))7608 updates.resize(q);7609 }7610 return {arr, updates};7611}76127613} // namespace hack76147615/*********************7616 * *7617 * MISCELLANEOUS *7618 * *7619 *********************/76207621namespace misc {76227623// Generates a uniformly random balanced parentheses sequence with k '(' and k7624// ')'. Valid means that for no prefix there are more ')' than '('.7625// O(size).7626inline std::string gen_parenthesis(int size) {7627 tgen_ensure(size > 0 and size % 2 == 0,7628 "misc: parenthesis: size must be a positive even number");76297630 int k = size / 2;7631 std::string s;7632 int open = 0, close = 0;76337634 for (int i = 0; i < size; ++i) {7635 if (open == k) {7636 s += ')';7637 ++close;7638 continue;7639 }7640 if (open == close) {7641 s += '(';7642 ++open;7643 continue;7644 }76457646 long long a = k - open, b = k - close, h = open - close;76477648 // Probability of placing '(':7649 // P('(') = (k - open) * (h + 2) / ((k - open + k - close) * (h + 1))7650 // Derived from ballot numbers ratio.7651 long long num = a * (h + 2);7652 long long den = (a + b) * (h + 1);76537654 if (next<long long>(1, den) <= num) {7655 s += '(';7656 ++open;7657 } else {7658 s += ')';7659 ++close;7660 }7661 }76627663 return s;7664}76657666} // namespace misc76677668} // namespace tgen