tgen 1.4.0
Loading...
Searching...
No Matches
tgen.h
1/*
2 * Copyright (c) 2026 Bruno Monteiro
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * 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 IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#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>
47
48namespace tgen {
49
50/**************************
51 * *
52 * GENERAL OPERATIONS *
53 * *
54 **************************/
55
56namespace detail {
57
58// Type aliases.
59using u128 = unsigned __int128;
60using i128 = __int128;
61
62/*
63 * Error handling.
64 */
65
66inline 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_error
91complex_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}
109
110// 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__)
115
116// 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}
123
124// Template magic to detect types at compile time.
125
126// 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 variants
135template <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 {};
147
148// 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_scalar
159 : std::bool_constant<!is_container<T>::value and !is_tuple<T>::value and
160 !is_pair<T>::value> {};
161// Detects complex container.
162template <typename T>
163struct is_container_multiline
164 : std::bool_constant<is_container<T>::value and
165 !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 ...)> {};
178
179// Used to return false at compile time only if evaluated.
180template <typename> inline constexpr bool dependent_false_v = false;
181
182/*
183 * Properties of custom types.
184 */
185
186// If type is sequential (list-like).
187using is_sequential_tag = void;
188
189// 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 {};
196
197// 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 {};
204
205/*
206 * Unique rng to use.
207 */
208
209// The single rng to be used by the library.
210inline std::mt19937 rng;
211
212/*
213 * Printing.
214 */
215
216// Print view struct for printing either a container or a sequential generator
217// element.
218template <typename T,
219 bool IsCont = detail::is_container<std::decay_t<T>>::value>
220struct print_cols_view;
221
222// Container.
223template <typename T> struct print_cols_view<T, true> {
224 const T &value;
225 decltype(std::begin(std::declval<const T &>())) it;
226
227 print_cols_view(const T &v) : value(v), it(v.begin()) {}
228
229 std::size_t size() const { return value.size(); }
230 decltype(auto) get(std::size_t) const { return *it; }
231 void advance() { ++it; }
232};
233
234// Sequential generator element.
235template <typename T> struct print_cols_view<T, false> {
236 const T &value;
237
238 print_cols_view(const T &v) : value(v) {}
239
240 std::size_t size() const { return value.size(); }
241 decltype(auto) get(std::size_t i) const {
242 return value[static_cast<int>(i)];
243 }
244 void advance() {}
245};
246
247/*
248 * Distinct generation.
249 */
250
251// Rejection cap is multiplier * |seen|; with one value left, falsely reporting
252// exhaustion has probability about e^{-84} < 10^{-36}.
253constexpr int distinct_attempt_multiplier = 84;
254
255// One rejection-sampling step for distinct generation.
256// O(T * log k + log^2 k) amortized expected time per call when generating k
257// distinct values and next() runs in O(T).
258template <typename Seen, typename Fn>
259auto try_generate_distinct(Seen &seen, Fn &&next, bool insert = true)
260 -> std::optional<std::invoke_result_t<Fn &>> {
261 using T = std::invoke_result_t<Fn &>;
262 size_t attempts =
263 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());
264 for (size_t i = 0; i < attempts; ++i) {
265 T val = next();
266 if (insert) {
267 if (seen.insert(val).second)
268 return val;
269 } else if (seen.count(val) == 0)
270 return val;
271 }
272 return std::nullopt;
273}
274
275} // namespace detail
276
277/*
278 * Compiler configuration (see set_compiler).
279 */
280
281// Kinds of compilers.
282enum class compiler_kind { gcc, clang, unknown };
283
284// Compiler identity and version.
286 compiler_kind kind_;
287 int major_;
288 int minor_;
289
290 compiler_value(compiler_kind kind = compiler_kind::unknown, int major = 0,
291 int minor = 0)
292 : kind_(kind), major_(major), minor_(minor) {}
293};
294
295namespace detail {
296
297// Global C++ version value (0 means unknown).
298struct cpp_value {
299 int version_;
300
301 cpp_value(std::optional<int> version = std::nullopt)
302 : version_(version ? *version : 0) {
303 if (version) {
304 tgen_ensure(*version == 17 or *version == 20 or *version == 23,
305 "unsupported C++ version (use 17, 20, 23)");
306 }
307 }
308};
309
310inline cpp_value cpp;
311inline compiler_value compiler;
312
313} // namespace detail
314
315/*
316 * Base classes.
317 */
318
319// Needed for return type of some functions.
320template <typename T> struct list;
321
322// Generates distinct values of a function.
323template <typename Func, typename... Args> struct distinct {
324 Func func_;
325 std::tuple<Args...> args_;
326 using T = std::invoke_result_t<Func &, Args &...>;
327 std::set<T> seen_;
328
329 distinct(Func func, Args... args)
330 : func_(std::move(func)), args_(std::move(args)...) {}
331
332 // Generates a distinct value (i.e., one not returned before).
333 //
334 // Assume gen() produces a uniformly random value in O(T) time.
335 // Since duplicates are rejected, the expected number of trials over
336 // k successful generations is:
337 //
338 // sum_{i=1}^k k / i = O(k log k)
339 //
340 // (coupon collector argument).
341 //
342 // Each trial additionally performs O(log k) work to check/store
343 // previously generated values, yielding a total time of
344 // O((T + log k) * k log k).
345 //
346 // Thus, the amortized expected time per call is
347 // O(T * log k + log^2 k).
348 //
349 // With extremely small probability (< 1e-18), the algorithm may
350 // incorrectly report that no more distinct values exist.
351 auto gen() {
352 auto val = generate_distinct(true);
353 if (val)
354 return *val;
355
356 throw detail::error("distinct: no more distinct values");
357 }
358 template <typename U> auto gen(std::initializer_list<U> il) {
359 return gen(std::vector<U>(il));
360 }
361
362 // Generates a list of distinct values.
363 auto gen_list(int size) {
364 std::vector<T> res;
365 for (int i = 0; i < size; ++i)
366 res.push_back(gen());
367
368 return typename list<T>::value(res);
369 }
370
371 // Checks if there are no more distinct values.
372 // With extremely small probability (< 1e-18), the algorithm may
373 // incorrectly report that there are no more distinct values.
374 bool empty() { return generate_distinct(false) == std::nullopt; }
375
376 // Generates all distinct values.
377 auto gen_all() {
378 std::vector<T> res;
379 while (true) {
380 auto val = generate_distinct(true);
381 if (val)
382 res.push_back(*val);
383 else
384 break;
385 }
386 return typename list<T>::value(res);
387 }
388
389 // Nice error for `out << distinct`.
390 friend std::ostream &operator<<(std::ostream &out, const distinct &) {
391 static_assert(
392 detail::dependent_false_v<distinct>,
393 "distinct: cannot print a distinct generator. Maybe you forgot to "
394 "call `gen()`?");
395 return out;
396 }
397
398 private:
399 // Generates distinct value and inserts it if `insert` is true.
400 // Returns the value if found, otherwise returns std::nullopt.
401 auto generate_distinct(bool insert) {
402 return detail::try_generate_distinct(
403 seen_, [&] { return std::apply(func_, args_); }, insert);
404 }
405};
406template <typename Func, typename... Args>
407distinct(Func, Args...) -> distinct<Func, Args...>;
408
409// Base struct for generators.
410template <typename Gen> struct gen_base {
411 const Gen &self() const { return *static_cast<const Gen *>(this); }
412
413 template <typename... Args> auto gen_list(int size, Args &&...args) const {
414 std::vector<typename Gen::value> res;
415
416 for (int i = 0; i < size; ++i)
417 res.push_back(static_cast<const Gen *>(this)->gen(
418 std::forward<Args>(args)...));
419
420 return typename list<typename Gen::value>::value(res);
421 }
422
423 // Calls the generator until predicate is true.
424 template <typename Pred, typename... Args>
425 auto gen_until(Pred predicate, int max_tries, Args &&...args) const {
426 for (int i = 0; i < max_tries; ++i) {
427 typename Gen::value val = static_cast<const Gen *>(this)->gen(
428 std::forward<Args>(args)...);
429
430 if (predicate(val))
431 return val;
432 }
433
434 throw detail::error("could not generate value matching predicate");
435 }
436 template <typename Pred, typename T, typename... Args>
437 auto gen_until(Pred predicate, int max_tries, std::initializer_list<T> il,
438 Args &&...args) const {
439 return gen_until(predicate, max_tries, std::vector<T>(il),
440 std::forward<Args>(args)...);
441 }
442
443 // Distinct for generator.
444 template <typename... Args> auto distinct(Args &&...args) const {
445 return tgen::distinct(
446 [self = self()](auto &&...inner_args) mutable -> decltype(auto) {
447 return self.gen(
448 std::forward<decltype(inner_args)>(inner_args)...);
449 },
450 std::forward<Args>(args)...);
451 }
452 template <typename T, typename... Args>
453 auto distinct(std::initializer_list<T> il, Args &&...args) const {
454 return distinct(std::vector<T>(il), std::forward<Args>(args)...);
455 }
456
457 // Nice error for `out << generator`.
458 friend std::ostream &operator<<(std::ostream &out, const gen_base &) {
459 static_assert(detail::dependent_false_v<gen_base>,
460 "gen_base: cannot print a generator. Maybe you forgot to "
461 "call `gen()`?");
462 return out;
463 }
464};
465
466// Base class for generator values.
467template <typename Val> struct gen_value_base {
468 const Val &self() const { return *static_cast<const Val *>(this); }
469
470 bool operator<(const Val &rhs) const {
471 return self().to_std() < rhs.to_std();
472 }
473};
474
475namespace detail {
476
477// Detects generator values.
478template <typename T>
479struct is_generator_value
480 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};
481
482} // namespace detail
483
484/*
485 * Easier printing.
486 */
487
488// Struct to print standard types to std::ostream;
489struct print {
490 std::string s_;
491
492 template <typename T> print(const T &val, char sep = ' ') {
493 std::ostringstream oss;
494 write(oss, val, sep);
495 s_ = oss.str();
496 }
497 template <typename T>
498 print(const std::initializer_list<T> &il, char sep = ' ') {
499 std::ostringstream oss;
500 write(oss, std::vector<T>(il), sep);
501 s_ = oss.str();
502 }
503 template <typename T>
504 print(const std::initializer_list<std::initializer_list<T>> &il,
505 char sep = ' ') {
506 std::ostringstream oss;
507 std::vector<std::vector<T>> mat;
508 for (const auto &i : il)
509 mat.push_back(i);
510 write(oss, mat, sep);
511 s_ = oss.str();
512 }
513
514 template <typename T> void write(std::ostream &os, const T &val, char sep) {
515 if constexpr (detail::is_pair<T>::value) {
516 if constexpr (detail::is_pair_multiline<T>::value) {
517 write(os, val.first, sep);
518 os << '\n';
519 write(os, val.second, sep);
520 } else {
521 // Use space for inner separator.
522 write(os, val.first, ' ');
523 os << sep;
524 write(os, val.second, ' ');
525 }
526 } else if constexpr (detail::is_tuple<T>::value)
527 write_tuple(os, val, sep);
528 else if constexpr (detail::is_container<T>::value)
529 write_container(os, val, sep);
530 else if constexpr (std::is_same_v<T, detail::i128> or
531 std::is_same_v<T, detail::u128>)
532 write_128_number(os, val);
533 else
534 os << val;
535 }
536
537 // Writes 128 bit number.
538 template <typename T> void write_128_number(std::ostream &os, T num) {
539 static const long long BASE = 1e18;
540
541 if (num < 0) {
542 os << '-';
543 num = -num;
544 }
545
546 if (num >= BASE) {
547 write_128_number(os, num / BASE);
548 os << std::setw(18) << std::setfill('0')
549 << static_cast<long long>(num % BASE);
550 } else
551 os << static_cast<long long>(num);
552 }
553 // Writes container, checking separator.
554 template <typename C>
555 void write_container(std::ostream &os, const C &container, char sep) {
556 bool first = true;
557
558 for (const auto &e : container) {
559 if (!first)
560 os << (detail::is_container_multiline<C>::value ? '\n' : sep);
561 first = false;
562 write(os, e, detail::is_container_multiline<C>::value ? sep : ' ');
563 }
564 }
565
566 // Writes tuple, checking separator.
567 template <typename Tuple, size_t... I>
568 void write_tuple_impl(std::ostream &os, const Tuple &tp, char sep,
569 std::index_sequence<I...>) {
570 bool first = true;
571 ((os << (first ? (first = false, "")
572 : (detail::is_tuple_multiline<Tuple>::value
573 ? "\n"
574 : std::string(1, sep))),
575 write(os, std::get<I>(tp),
576 detail::is_tuple_multiline<Tuple>::value ? sep : ' ')),
577 ...);
578 }
579 template <typename T>
580 void write_tuple(std::ostream &os, const T &tp, char sep) {
581 write_tuple_impl(os, tp, sep,
582 std::make_index_sequence<std::tuple_size<T>::value>{});
583 }
584
585 friend std::ostream &operator<<(std::ostream &out, const print &pr) {
586 return out << pr.s_;
587 }
588};
589
590// Prints in a new line.
591struct println : print {
592 template <typename T>
593 println(const T &val, char sep = ' ') : print(val, sep) {}
594 template <typename T>
595 println(const std::initializer_list<T> &il, char sep = ' ')
596 : print(il, sep) {}
597 template <typename T>
598 println(const std::initializer_list<std::initializer_list<T>> &il,
599 char sep = ' ')
600 : print(il, sep) {}
601
602 friend std::ostream &operator<<(std::ostream &out, const println &pr) {
603 return out << pr.s_ << '\n';
604 }
605};
606
607// Prints container / sequential generator value on its own column.
608// Example:
609// A = {1, 2, 3}, B = {4, 2, 5}
610// print_each(A, B) will print:
611// "1 4
612// 2 2
613// 3 5
614//",
615// that is, it prints the end of the line for all lines.
616template <typename... Args> struct print_cols {
617 std::string s_;
618
619 print_cols(const Args &...args) {
620 static_assert(
621 ((detail::is_container<std::decay_t<Args>>::value or
622 detail::is_sequential<std::decay_t<Args>>::value) and
623 ...),
624 "print_cols: arguments must be containers or sequential generator "
625 "values");
626 std::ostringstream oss;
627 write(oss, args...);
628 s_ = oss.str();
629 }
630
631 void write(std::ostream &os, const Args &...args) {
632 auto views = std::apply(
633 [](const Args &...inner_args) {
634 return std::make_tuple(
635 detail::print_cols_view<decltype(inner_args)>{
636 inner_args}...);
637 },
638 std::forward_as_tuple(args...));
639
640 const std::size_t n = std::get<0>(views).size();
641
642 auto check = [&](const auto &v) {
643 tgen_ensure(v.size() == n, "print_cols: sizes should be the same");
644 };
645 std::apply([&](const auto &...v) { (check(v), ...); }, views);
646
647 for (std::size_t i = 0; i < n; ++i) {
648 bool first = true;
649
650 std::apply(
651 [&](const auto &...v) {
652 ((os << (first ? "" : " ") << print(v.get(i)),
653 first = false),
654 ...);
655 },
656 views);
657
658 os << '\n';
659
660 std::apply([](auto &...v) { (v.advance(), ...); }, views);
661 }
662 }
663
664 friend std::ostream &operator<<(std::ostream &out, const print_cols &pr) {
665 return out << pr.s_;
666 }
667};
668
669/*
670 * Global random operations.
671 */
672
673namespace detail {
674
675// libstdc++ accepts std::uniform_int_distribution with narrow integral types
676// (char/signed char/unsigned char/short/bool), but libc++ rejects them with a
677// hard static_assert ("IntType must be a supported integer type"). Promote such
678// types to a width the standard guarantees, preserving signedness, so the same
679// `next<T>` works across both standard libraries (e.g. Apple clang / libc++).
680template <typename T>
681using uniform_int_t = std::conditional_t<
682 (sizeof(T) >= sizeof(short)), T,
683 std::conditional_t<std::is_signed_v<T>, int, unsigned int>>;
684
685} // namespace detail
686
687// Returns a uniformly random number in [0, right)
688// O(1).
689template <typename T> T next(T right) {
690 detail::ensure_registered();
691 if constexpr (std::is_integral_v<T>) {
692 tgen_ensure(right >= 1, "value for `next` must be valid");
693 return static_cast<T>(
694 std::uniform_int_distribution<detail::uniform_int_t<T>>(
695 0,
696 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));
697 } else if constexpr (std::is_floating_point_v<T>) {
698 tgen_ensure(right >= 0, "value for `next` must be valid");
699 return std::uniform_real_distribution<T>(0, right)(detail::rng);
700 } else
701 throw detail::error("invalid type for next (" +
702 std::string(typeid(T).name()) + ")");
703}
704
705// Returns a uniformly random number in [left, right].
706// For floating-point types, uses uniform_real_distribution ([left, right) in
707// C++), equivalent to [left, right] because the right endpoint has probability
708// zero.
709// O(1).
710template <typename T> T next(T left, T right) {
711 detail::ensure_registered();
712 tgen_ensure(left <= right, "range for `next` must be valid");
713 if constexpr (std::is_integral_v<T>)
714 return static_cast<T>(
715 std::uniform_int_distribution<detail::uniform_int_t<T>>(
716 static_cast<detail::uniform_int_t<T>>(left),
717 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));
718 else if constexpr (std::is_floating_point_v<T>)
719 return std::uniform_real_distribution<T>(left, right)(detail::rng);
720 else
721 throw detail::error("invalid type for next (" +
722 std::string(typeid(T).name()) + ")");
723}
724
725// Skewed next.
726//
727// Returns a random number in [0, right) with a bias controlled by `w`.
728// - w = 0:
729// Uniform distribution.
730// - w > 0:
731// Returns the maximum of (w + 1) independent uniform samples.
732// Biases the distribution toward larger values.
733// The resulting density is proportional to:
734// f(x) = x^w
735// In particular:
736// w = 1 -> linear bias
737// w = 2 -> quadratic bias
738// w = 3 -> cubic bias
739// - w < 0:
740// Returns the minimum of (-w + 1) independent uniform samples.
741// Symmetric to the w > 0 case.
742// The continuous version corresponds to Beta distributions:
743// w > 0 -> Beta(w + 1, 1)
744// w < 0 -> Beta(1, -w + 1)
745// For |w| > 5, the distribution is approximate.
746// O(1).
747template <typename T> T wnext(T right, int w) {
748 // For small |w|, use the naive approach.
749 if (abs(w) <= 5) {
750 T val = next<T>(right);
751 for (int i = 0; i < w; ++i)
752 val = std::max(val, next<T>(right));
753 for (int i = 0; i < -w; ++i)
754 val = std::min(val, next<T>(right));
755 return val;
756 }
757
758 // O(1) way.
759 double x, r = next<double>(0, 1);
760
761 if (w >= 0) {
762 x = std::pow(r, 1.0 / (w + 1));
763 } else {
764 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
765 }
766
767 return T(x * right);
768}
769
770// Returns a random number in [left, right] with a bias controlled by `w`.
771// O(1).
772template <typename T> T wnext(T left, T right, int w) {
773 // For small |w|, use the naive approach.
774 if (abs(w) <= 5) {
775 T val = next<T>(left, right);
776 for (int i = 0; i < w; ++i)
777 val = std::max(val, next<T>(left, right));
778 for (int i = 0; i < -w; ++i)
779 val = std::min(val, next<T>(left, right));
780 return val;
781 }
782
783 // O(1) way.
784 double x, r = next<double>(0, 1);
785
786 if (w >= 0) {
787 x = std::pow(r, 1.0 / (w + 1));
788 } else {
789 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
790 }
791
792 return left + T(x * (right - left));
793}
794
795namespace detail {
796
797// Uniformly random 128 bit number in [0, total).
798// O(1) expected.
799inline u128 next128(u128 total) {
800 tgen_ensure(total > 0, "next128: total must be positive");
801
802 // Largest multiple of total less than 2^128.
803 u128 limit = (u128(-1) / total) * total;
804
805 while (true) {
806 // Generate uniform 128-bit random number.
807 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))
808 << 64) |
809 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());
810
811 if (r < limit)
812 return r % total;
813 }
814}
815
816} // namespace detail
817
818// Weighted sampler.
819//
820// Generates indices with probability proportional to `distribution`, using
821// alias method.
822//
823// Internally, integral weights are accumulated in unsigned __int128 (exact);
824// floating-point weights are accumulated in double.
825// <O(n), O(1)>.
826template <typename T> struct weighted_sampler {
827 static_assert(std::is_arithmetic_v<T>,
828 "weighted_sampler requires an arithmetic weight type");
829
830 // Internal storage type: `u128` for integral inputs (exact arithmetic),
831 // `double` for floating-point inputs.
832 using storage_t =
834
835 int n_;
836 std::vector<storage_t> weight_;
837 std::vector<int> alias_;
838 storage_t total_;
839
840 // Creates an alias method for generating indices with probability
841 // proportional to the distribution.
842 // O(n).
843 weighted_sampler(const std::vector<T> &distribution)
844 : n_(static_cast<int>(distribution.size())), alias_(n_) {
845 tgen_ensure(distribution.size() > 0,
846 "weighted_sampler: distribution must be non-empty");
847 for (const auto &w : distribution)
848 tgen_ensure(w >= 0,
849 "weighted_sampler: distribution must be non-negative");
850
851 total_ = std::accumulate(distribution.begin(), distribution.end(),
852 storage_t(0));
853
854 std::queue<int> big, small;
855 for (int i = 0; i < n_; ++i) {
856 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));
857 if (weight_[i] < total_)
858 small.push(i);
859 else
860 big.push(i);
861 }
862
863 while (!small.empty() and !big.empty()) {
864 int s = small.front();
865 small.pop();
866 int b = big.front();
867 big.pop();
868
869 alias_[s] = b;
870
871 weight_[b] -= total_ - weight_[s];
872 if (weight_[b] < total_)
873 small.push(b);
874 else
875 big.push(b);
876 }
877
878 detail::tgen_ensure_against_bug(
879 small.empty(), "weighted_sampler: small must be empty");
880
881 // The remaining elements should have weight equal to total and be
882 // assigned to themselves.
883 while (!big.empty()) {
884 int b = big.front();
885 big.pop();
886 if constexpr (std::is_integral_v<T>) {
887 detail::tgen_ensure_against_bug(
888 weight_[b] == total_,
889 "weighted_sampler: weight of big element must be total");
890 }
891 alias_[b] = b;
892 }
893 }
894 weighted_sampler(const std::initializer_list<T> &distribution)
895 : weighted_sampler(std::vector<T>(distribution)) {}
896
897 // Uniformly random value in [0, total). Overloaded so next() can dispatch
898 // at compile time to the right primitive for the chosen `storage_t`.
899 static detail::u128 sample_below(detail::u128 total) {
900 return detail::next128(total);
901 }
902 static double sample_below(double total) {
903 return tgen::next<double>(0, total);
904 }
905
906 // Generates a random index with probability proportional to the
907 // distribution.
908 // O(1).
909 size_t next() const {
910 int i = tgen::next<int>(0, n_ - 1);
911 return sample_below(total_) < weight_[i] ? i : alias_[i];
912 }
913};
914template <typename T>
915weighted_sampler(const std::vector<T> &) -> weighted_sampler<T>;
916template <typename T>
917weighted_sampler(const std::initializer_list<T> &) -> weighted_sampler<T>;
918
919// Returns i with probability proportional to distribution[i].
920// O(|distribution|).
921template <typename T>
922size_t next_by_distribution(const std::vector<T> &distribution) {
923 return weighted_sampler(distribution).next();
924}
925template <typename T>
926size_t next_by_distribution(const std::initializer_list<T> &distribution) {
927 return next_by_distribution(std::vector<T>(distribution));
928}
929
930// Returns a vector of k indices with probability proportional to
931// `distribution`. Uses alias method.
932// O(k + |distribution|).
933template <typename T>
935 const std::vector<T> &distribution) {
936 tgen_ensure(distribution.size() > 0, "distribution must be non-empty");
937 tgen_ensure(k >= 0, "number of elements to choose must be non-negative");
938
939 weighted_sampler am(distribution);
940 std::vector<int> res;
941 for (int i = 0; i < k; ++i)
942 res.push_back(static_cast<int>(am.next()));
943 return res;
944}
945template <typename T>
946std::vector<int>
947many_by_distribution(int k, const std::initializer_list<T> &distribution) {
948 return many_by_distribution(k, std::vector<T>(distribution));
949}
950
951// Shuffles [first, last) inplace uniformly, for RandomAccessIterator.
952// O(|container|).
953template <typename It> void shuffle(It first, It last) {
954 if (first == last)
955 return;
956
957 for (It i = first + 1; i != last; ++i)
958 std::iter_swap(i, first + next(0, static_cast<int>(i - first)));
959}
960
961// Shuffles container uniformly.
962// O(|container|).
963template <typename C> [[nodiscard]] auto shuffled(const C &container) {
964 if constexpr (detail::is_associative_container<C>::value) {
965 std::vector<typename C::value_type> vec(container.begin(),
966 container.end());
967 shuffle(vec.begin(), vec.end());
968 return vec;
969 } else {
970 auto new_container = container;
971 shuffle(new_container.begin(), new_container.end());
972 return new_container;
973 }
974}
975template <typename T>
976[[nodiscard]] std::vector<T> shuffled(const std::initializer_list<T> &il) {
977 return shuffled(std::vector<T>(il));
978}
979
980// Returns a random element from [first, last) uniformly.
981// O(1) for random_access_iterator, O(|last - first|) otherwise.
982template <typename It> typename It::value_type pick(It first, It last) {
983 int size = static_cast<int>(std::distance(first, last));
984 tgen_ensure(size > 0, "cannot pick from empty range");
985 It it = first;
986 std::advance(it, next(0, size - 1));
987 return *it;
988}
989
990// Returns a random element from container uniformly.
991// O(1) for random_access_iterator, O(|container|) otherwise.
992template <typename C> typename C::value_type pick(const C &container) {
993 return pick(container.begin(), container.end());
994}
995template <typename T> T pick(const std::initializer_list<T> &il) {
996 return pick(std::vector<T>(il));
997}
998
999// Returns container[i] with probability proportional to distribution[i].
1000// O(1) for random_access_iterator, O(|container|) otherwise.
1001template <typename C, typename T>
1002typename C::value_type pick_by_distribution(const C &container,
1003 std::vector<T> distribution) {
1004 tgen_ensure(container.size() == distribution.size(),
1005 "container and distribution must have the same size");
1006 auto it = container.begin();
1007 std::advance(it, next_by_distribution(distribution));
1008 return *it;
1009}
1010template <typename C, typename T>
1011typename C::value_type
1012pick_by_distribution(const C &container,
1013 const std::initializer_list<T> &distribution) {
1014 return pick_by_distribution(container, std::vector<T>(distribution));
1015}
1016template <typename T, typename U>
1017T pick_by_distribution(const std::initializer_list<T> &il,
1018 const std::vector<U> &distribution) {
1019 return pick_by_distribution(std::vector<T>(il), distribution);
1020}
1021template <typename T, typename U>
1022T pick_by_distribution(const std::initializer_list<T> &il,
1023 const std::initializer_list<U> &distribution) {
1024 return pick_by_distribution(std::vector<T>(il),
1025 std::vector<U>(distribution));
1026}
1027
1028// Chooses k values uniformly from container, as in a subsequence of size k.
1029// Returns a copy. O(|container|).
1030template <typename C> C choose(const C &container, int k) {
1031 tgen_ensure(0 < k and k <= static_cast<int>(container.size()),
1032 "number of elements to choose must be valid");
1033 std::vector<typename C::value_type> new_vec;
1034 C new_container;
1035 int need = k, left = static_cast<int>(container.size());
1036 for (auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {
1037 if (next(1, left--) <= need) {
1038 new_container.insert(new_container.end(), *cur_it);
1039 need--;
1040 }
1041 }
1042 return new_container;
1043}
1044template <typename T>
1045std::vector<T> choose(const std::initializer_list<T> &il, int k) {
1046 return choose(std::vector<T>(il), k);
1047}
1048
1049// Number distinct generator for integral types.
1050// Optimized for performance (unordered_map virtual list; gen_list uses array
1051// pool, complement, or sparse sampling).
1052template <typename T> struct distinct_range {
1053 T left_, right_;
1054 T num_available_;
1055 std::unordered_map<T, T> virtual_list_;
1056
1057 // When the range fits in memory, sample via array Fisher–Yates.
1058 static constexpr size_t array_pool_max = size_t{1} << 23;
1059
1060 // Generator of distinct values in [left, right].
1061 distinct_range(T left, T right)
1062 : left_(left), right_(right),
1063 num_available_(static_cast<T>(right - left + 1)) {}
1064
1065 // Returns the number of distinct values left to generate.
1066 T size() const { return num_available_; }
1067
1068 // Generates a random value in [left_, right_] that has not been generated
1069 // yet.
1070 // O(log n).
1071 T gen() {
1072 // One iteration of Fisher–Yates.
1073 tgen_ensure(size() > 0, "distinct_range: no more values to generate");
1074
1075 T i = next<T>(0, size() - 1);
1076 T j = size() - 1;
1077
1078 auto vi_it = virtual_list_.find(i);
1079 T vi = vi_it == virtual_list_.end() ? i : vi_it->second;
1080 auto vj_it = virtual_list_.find(j);
1081 T vj = vj_it == virtual_list_.end() ? j : vj_it->second;
1082 virtual_list_[i] = vj;
1083
1084 --num_available_;
1085
1086 return vi + left_;
1087 }
1088
1089 // Generates a list of distinct values.
1090 // Optimized for performance (array pool, complement, or sparse sampling).
1091 // O(size) when the range fits in memory; O(size log range) otherwise.
1092 auto gen_list(int count) {
1093 tgen_ensure(count >= 0, "distinct_range: size must be nonnegative");
1094 tgen_ensure(count <= num_available_,
1095 "distinct_range: no more values to generate");
1096
1097 size_t range_size = static_cast<size_t>(right_ - left_ + 1);
1098 size_t sample_count = static_cast<size_t>(count);
1099
1100 std::vector<T> res;
1101 if (sample_count > 0) {
1102 if (range_size <= array_pool_max)
1103 res = sample_from_pool(sample_count, range_size);
1104 else if (sample_count * 2 > range_size)
1105 res = sample_complement(sample_count, range_size);
1106 else
1107 res = sample_sparse(sample_count);
1108 }
1109
1110 num_available_ -= static_cast<T>(count);
1111 virtual_list_.clear();
1112 return typename list<T>::value(res);
1113 }
1114
1115 // Generates all distinct values.
1116 // O(n) when the range fits in memory; O(n log n) otherwise.
1117 auto gen_all() { return gen_list(size()); }
1118
1119 private:
1120 // Samples count distinct values via array Fisher–Yates on [left_, right_].
1121 // O(range_size) time and memory.
1122 std::vector<T> sample_from_pool(size_t count, size_t range_size) {
1123 std::vector<T> pool(range_size);
1124 std::iota(pool.begin(), pool.end(), left_);
1125 for (size_t i = 0; i < count; ++i) {
1126 size_t j = next<size_t>(i, range_size - 1);
1127 std::swap(pool[i], pool[j]);
1128 }
1129 pool.resize(count);
1130 return pool;
1131 }
1132
1133 // Samples count distinct values by excluding range_size - count values.
1134 // O(range_size + (range_size - count) log(range_size)).
1135 std::vector<T> sample_complement(size_t count, size_t range_size) {
1136 size_t exclude_count = range_size - count;
1137 std::unordered_set<T> excluded;
1138 excluded.reserve(exclude_count * 2);
1139
1140 if (exclude_count <= array_pool_max) {
1141 for (T value : sample_from_pool(exclude_count, range_size))
1142 excluded.insert(value);
1143 } else {
1144 for (T value : sample_sparse(exclude_count))
1145 excluded.insert(value);
1146 }
1147
1148 std::vector<T> res;
1149 res.reserve(count);
1150 for (T value = left_; value <= right_; ++value) {
1151 if (!excluded.count(value))
1152 res.push_back(value);
1153 }
1154 detail::tgen_ensure_against_bug(
1155 res.size() == count, "distinct_range: complement sampling failed");
1156 return res;
1157 }
1158
1159 // Samples count distinct values via sparse-map Fisher–Yates.
1160 // O(count log(range_size)).
1161 std::vector<T> sample_sparse(size_t count) {
1162 std::unordered_map<T, T> local_virtual;
1163 local_virtual.reserve(count * 2);
1164 T remaining = range_span();
1165 std::vector<T> res;
1166 res.reserve(count);
1167 for (size_t step = 0; step < count; ++step) {
1168 T i = next<T>(0, remaining - 1);
1169 T j = remaining - 1;
1170
1171 auto vi_it = local_virtual.find(i);
1172 T vi = vi_it == local_virtual.end() ? i : vi_it->second;
1173 auto vj_it = local_virtual.find(j);
1174 T vj = vj_it == local_virtual.end() ? j : vj_it->second;
1175 local_virtual[i] = vj;
1176
1177 res.push_back(vi + left_);
1178 --remaining;
1179 }
1180 return res;
1181 }
1182
1183 // Returns right_ - left_ + 1.
1184 // O(1).
1185 T range_span() { return static_cast<T>(right_ - left_ + 1); }
1186};
1187
1188// Distinct generator for containers.
1189template <typename T> struct distinct_container {
1190 std::vector<T> list_;
1191 distinct_range<size_t> idx_;
1192
1193 // Creates a distinct container generator for the given container.
1194 template <typename C>
1195 distinct_container(const C &container)
1197 idx_(0, static_cast<int>(container.size()) - 1) {}
1198 distinct_container(const std::initializer_list<T> &il)
1199 : distinct_container(std::vector<T>(il)) {}
1200
1201 // Returns the number of distinct elements left to generate.
1202 size_t size() const { return idx_.size(); }
1203
1204 // Generates a random element from container uniformly.
1205 // O(log n).
1206 T gen() { return list_[idx_.gen()]; }
1207
1208 // Generates a list of distinct values.
1209 // O(size * log(n)).
1210 auto gen_list(int size) {
1211 std::vector<T> res;
1212 for (int i = 0; i < size; ++i)
1213 res.push_back(gen());
1214 return typename list<T>::value(res);
1215 }
1216
1217 // Generates all distinct values.
1218 // O(n log(n))
1219 auto gen_all() {
1220 std::vector<T> res;
1221 while (size() > 0)
1222 res.push_back(gen());
1223 return typename list<T>::value(res);
1224 }
1225};
1226template <typename C>
1227distinct_container(const C &) -> distinct_container<typename C::value_type>;
1228
1229/************
1230 * *
1231 * OPTS *
1232 * *
1233 ************/
1234
1235/*
1236 * Opts - options given to the generator.
1237 *
1238 * Incompatible with testlib.
1239 *
1240 * Opts are a list of either positional or named options.
1241 *
1242 * Named options are given in one of the following formats:
1243 * 1) -keyname=value or --keyname=value (ex. -n=10 , --test-count=20)
1244 * 2) -keyname value or --keyname value (ex. -n 10 , --test-count 20)
1245 *
1246 * Positional options are numbered from 0 sequentially.
1247 * For example, for "10 -n=20 str" positional option 1 is the string "str".
1248 */
1249
1250/*
1251 * C++ version selection.
1252 */
1253
1254// Sets C++ version.
1255inline void set_cpp_version(int version) {
1256 detail::cpp = detail::cpp_value(version);
1257}
1258
1259/*
1260 * Compiler selection.
1261 */
1262
1263// GCC compiler type.
1264inline compiler_value gcc(int major = 0, int minor = 0) {
1265 return {compiler_kind::gcc, major, minor};
1266}
1267
1268// Clang compiler type.
1269inline compiler_value clang(int major = 0, int minor = 0) {
1270 return {compiler_kind::clang, major, minor};
1271}
1272
1273// Sets compiler.
1274inline void set_compiler(compiler_value compiler) {
1275 detail::compiler.kind_ = compiler.kind_;
1276 detail::compiler.major_ = compiler.major_;
1277 detail::compiler.minor_ = compiler.minor_;
1278}
1279
1280namespace detail {
1281
1282// Processes special opt flags.
1283// Returns true if the key is a special opt flag.
1284inline bool process_special_opt_flags(std::string &key) {
1285 // Checks for gen::CPP=17|20|23
1286 if (key.find("tgen::CPP:") == 0) {
1287 size_t prefix_len = std::string("tgen::CPP:").size();
1288 tgen_ensure(key.size() == prefix_len + 2 and
1289 std::isdigit(key[prefix_len]) and
1290 std::isdigit(key[prefix_len + 1]),
1291 "invalid CPP format");
1292 int version = std::stoi(key.substr(prefix_len, 2));
1293 set_cpp_version(version);
1294 return true;
1295 }
1296
1297 // Checks for tgen::(GCC|CLANG) or
1298 // tgen::(GCC|CLANG):(version|version.minor).
1299 compiler_kind kind;
1300 size_t prefix_len = 0;
1301
1302 if (key.find("tgen::GCC") == 0) {
1303 kind = compiler_kind::gcc;
1304 prefix_len = std::string("tgen::GCC").size();
1305 } else if (key.find("tgen::CLANG") == 0) {
1306 kind = compiler_kind::clang;
1307 prefix_len = std::string("tgen::CLANG").size();
1308 } else {
1309 return false;
1310 }
1311
1312 if (key.size() == prefix_len) {
1313 set_compiler(compiler_value(kind, 0, 0));
1314 return true;
1315 }
1316
1317 tgen_ensure(key[prefix_len] == ':', "invalid compiler format");
1318 ++prefix_len; // for ':'.
1319
1320 std::string inside = key.substr(prefix_len, key.size() - prefix_len);
1321 int major = 0, minor = 0;
1322
1323 size_t dot = inside.find('.');
1324 if (dot == std::string::npos) {
1325 tgen_ensure(!inside.empty() and
1326 std::all_of(inside.begin(), inside.end(), ::isdigit),
1327 "invalid compiler version");
1328 major = std::stoi(inside);
1329 } else {
1330 std::string maj = inside.substr(0, dot);
1331 std::string min = inside.substr(dot + 1);
1332
1333 tgen_ensure(!maj.empty() and
1334 std::all_of(maj.begin(), maj.end(), ::isdigit) and
1335 maj.size() <= 3,
1336 "invalid compiler major version");
1337 tgen_ensure(!min.empty() and
1338 std::all_of(min.begin(), min.end(), ::isdigit) and
1339 min.size() <= 3,
1340 "invalid compiler minor version");
1341
1342 major = std::stoi(maj);
1343 minor = std::stoi(min);
1344 }
1345
1346 set_compiler(compiler_value(kind, major, minor));
1347
1348 return true;
1349}
1350
1351inline std::vector<std::string>
1352 pos_opts; // Dictionary containing the positional parsed opts.
1353inline std::map<std::string, std::string>
1354 named_opts; // Global dictionary the named parsed opts.
1355
1356template <typename T> T get_opt(const std::string &value) {
1357 try {
1358 if constexpr (std::is_same_v<T, bool>) {
1359 if (value == "true" or value == "1")
1360 return true;
1361 if (value == "false" or value == "0")
1362 return false;
1363 } else if constexpr (std::is_integral_v<T>) {
1364 if constexpr (std::is_unsigned_v<T>)
1365 return static_cast<T>(std::stoull(value));
1366 else
1367 return static_cast<T>(std::stoll(value));
1368 } else if constexpr (std::is_floating_point_v<T>)
1369 return static_cast<T>(std::stold(value));
1370 else
1371 return value; // Default: std::string.
1372 } catch (...) {
1373 }
1374
1375 throw error("invalid value `" + value + "` for type " + typeid(T).name());
1376}
1377
1378inline void parse_opts(int argc, char **argv) {
1379 // Parses the opts into `pos_opts` vector and `named_opts`
1380 // map. Starting from 1 to ignore the name of the executable.
1381 for (int i = 1; i < argc; ++i) {
1382 std::string key(argv[i]);
1383
1384 if (process_special_opt_flags(key))
1385 continue;
1386
1387 if (key[0] == '-') {
1388 tgen_ensure(key.size() > 1,
1389 "invalid opt (" + std::string(argv[i]) + ")");
1390 if ('0' <= key[1] and key[1] <= '9') {
1391 // This case is a positional negative number argument.
1392 pos_opts.push_back(key);
1393 continue;
1394 }
1395
1396 // Pops first char '-'.
1397 key = key.substr(1);
1398 } else {
1399 // This case is a positional argument that does not start with '-'.
1400 pos_opts.push_back(key);
1401 continue;
1402 }
1403
1404 // Pops a possible second char '-'.
1405 if (key[0] == '-') {
1406 tgen_ensure(key.size() > 1,
1407 "invalid opt (" + std::string(argv[i]) + ")");
1408
1409 // Pops first char '-'.
1410 key = key.substr(1);
1411 }
1412
1413 // Assumes that, if it starts with '-' and second char is not a digit,
1414 // then it is a <key, value> pair.
1415 // 1 or 2 chars '-' have already been popped.
1416
1417 std::size_t eq = key.find('=');
1418 if (eq != std::string::npos) {
1419 // This is the '--key=value' case.
1420 std::string value = key.substr(eq + 1);
1421 key = key.substr(0, eq);
1422 tgen_ensure(!key.empty() and !value.empty(),
1423 "expected non-empty key/value in opt (" +
1424 std::string(argv[i]) + ")");
1425 tgen_ensure(named_opts.count(key) == 0,
1426 "cannot have repeated keys");
1427 named_opts[key] = value;
1428 } else {
1429 // This is the '--key value' case.
1430 tgen_ensure(named_opts.count(key) == 0,
1431 "cannot have repeated keys");
1432 tgen_ensure(argv[i + 1], "value cannot be empty");
1433 named_opts[key] = std::string(argv[i + 1]);
1434 ++i;
1435 }
1436 }
1437}
1438
1439inline void set_seed(int argc, char **argv) {
1440 std::vector<uint32_t> seed;
1441
1442 // Starting from 1 to ignore the name of the executable.
1443 for (int i = 1; i < argc; ++i) {
1444 // We append the number of chars, and then the list of chars.
1445 size_t size_pos = seed.size();
1446 seed.push_back(0);
1447 for (char *s = argv[i]; *s != '\0'; ++s) {
1448 ++seed[size_pos];
1449 seed.push_back(*s);
1450 }
1451 }
1452 std::seed_seq seq(seed.begin(), seed.end());
1453 rng.seed(seq);
1454}
1455
1456} // namespace detail
1457
1458// Returns true if there is an opt at a given index.
1459inline bool has_opt(std::size_t index) {
1460 detail::ensure_registered();
1461 return index < detail::pos_opts.size();
1462}
1463
1464// Returns true if there is an opt with a given key.
1465inline bool has_opt(const std::string &key) {
1466 detail::ensure_registered();
1467 return detail::named_opts.count(key) != 0;
1468}
1469template <typename K>
1470std::enable_if_t<std::is_same_v<K, char>, bool> has_opt(K key) {
1471 return has_opt(std::string(1, key));
1472}
1473
1474// Returns the parsed opt by a given index. If no opts with the given index are
1475// found, returns the given default_value.
1476template <typename T>
1477T opt(size_t index, std::optional<T> default_value = std::nullopt) {
1478 detail::ensure_registered();
1479 if (!has_opt(index)) {
1480 if (default_value)
1481 return *default_value;
1482 throw detail::error("cannot find opt at index " +
1483 std::to_string(index));
1484 }
1485 return detail::get_opt<T>(detail::pos_opts[index]);
1486}
1487
1488// Returns the parsed opt by a given key. If no opts with the given key are
1489// found, returns the given default_value.
1490template <typename T>
1491T opt(const std::string &key, std::optional<T> default_value = std::nullopt) {
1492 detail::ensure_registered();
1493 if (!has_opt(key)) {
1494 if (default_value)
1495 return *default_value;
1496 throw detail::error("cannot find opt with key " + key);
1497 }
1498 return detail::get_opt<T>(detail::named_opts[key]);
1499}
1500template <typename T, typename K>
1501std::enable_if_t<std::is_same_v<K, char>, T>
1502opt(K key, std::optional<T> default_value = std::nullopt) {
1503 return opt<T>(std::string(1, key), default_value);
1504}
1505
1506// Registers generator by initializing rng and parsing opts.
1507inline void register_gen(int argc, char **argv) {
1508 detail::set_seed(argc, argv);
1509
1510 detail::pos_opts.clear();
1511 detail::named_opts.clear();
1512 detail::parse_opts(argc, argv);
1513
1514 detail::registered = true;
1515}
1516
1517// Registers generator by initializing rng with a given seed.
1518inline void register_gen(std::optional<long long> seed = std::nullopt) {
1519 if (seed)
1520 detail::rng.seed(*seed);
1521 else
1522 detail::rng.seed();
1523
1524 detail::pos_opts.clear();
1525 detail::named_opts.clear();
1526
1527 detail::registered = true;
1528}
1529
1530/************
1531 * *
1532 * LIST *
1533 * *
1534 ************/
1535
1536/*
1537 * List generator.
1538 *
1539 * List of integral types.
1540 */
1541
1542template <typename T> struct list : gen_base<list<T>> {
1543 int size_; // Size of list.
1544 T value_l_, value_r_; // Range of defined values.
1545 std::set<T> values_; // Set of values. If empty, use range; if not,
1546 // represents the possible values, and the range
1547 // represents the index in this set.
1548 std::map<T, int>
1549 value_idx_in_set_; // Index of every value in the set above.
1550 mutable std::vector<std::pair<T, T>>
1551 val_range_; // Range of values of each index.
1552 mutable std::vector<std::vector<int>> neigh_; // Adjacency list of equality.
1553 std::vector<std::set<int>>
1554 diff_restrictions_; // All different restrictions.
1555 bool index_constraints_{
1556 false}; // True after fix/equal narrows per-index generation.
1557 mutable bool uses_full_range_{
1558 false}; // If true, every index uses [value_l_, value_r_] lazily.
1559
1560 // Creates generator for lists of size 'size', with random T in [value_left,
1561 // value_right].
1562 list(int size, T value_left, T value_right)
1563 : size_(size), value_l_(value_left), value_r_(value_right),
1564 uses_full_range_(true) {
1565 tgen_ensure(size_ > 0, "list: size must be positive");
1566 tgen_ensure(value_l_ <= value_r_, "list: value range must be valid");
1567 }
1568
1569 // Creates list with value set.
1570 list(int size, std::set<T> values)
1571 : size_(size), values_(values), index_constraints_(true) {
1572 tgen_ensure(size_ > 0, "list: size must be positive");
1573 tgen_ensure(!values.empty(), "list: value set must be non-empty");
1574 value_l_ = 0, value_r_ = static_cast<T>(values.size() - 1);
1575 val_range_.assign(size_, {value_l_, value_r_});
1576 int idx = 0;
1577 for (T val : values_)
1578 value_idx_in_set_[val] = idx++;
1579 }
1580
1581 // Restricts lists for list[idx] = val.
1582 list &fix(int idx, T val) {
1583 tgen_ensure(0 <= idx and idx < size_, "list: index must be valid");
1584 ensure_val_range_materialized();
1585 if (values_.size() == 0) {
1586 auto &[left, right] = val_range_[idx];
1587 if (left == right and value_l_ != value_r_) {
1588 tgen_ensure(left == val,
1589 "list: must not set to two different values");
1590 } else {
1591 tgen_ensure(left <= val and val <= right,
1592 "list: value must be in the defined range");
1593 }
1594 left = right = val;
1595 } else {
1596 tgen_ensure(values_.count(val),
1597 "list: value must be in the set of values");
1598 auto &[left, right] = val_range_[idx];
1599 T new_val = static_cast<T>(value_idx_in_set_[val]);
1600 tgen_ensure(left <= new_val and new_val <= right,
1601 "list: must not set to two different values");
1602 left = right = new_val;
1603 }
1604 index_constraints_ = true;
1605 return *this;
1606 }
1607
1608 // Restricts lists for list[idx_1] = list[idx_2].
1609 list &equal(int idx_1, int idx_2) {
1610 tgen_ensure(0 <= std::min(idx_1, idx_2) and
1611 std::max(idx_1, idx_2) < size_,
1612 "list: indices must be valid");
1613 if (idx_1 == idx_2)
1614 return *this;
1615
1616 ensure_val_range_materialized();
1617 ensure_neigh_allocated();
1618 index_constraints_ = true;
1619 neigh_[idx_1].push_back(idx_2);
1620 neigh_[idx_2].push_back(idx_1);
1621 return *this;
1622 }
1623
1624 // Restricts lists for list[S] to be equal, for given subset S of indices.
1625 list &equal(std::set<int> indices) {
1626 if (!indices.empty()) {
1627 std::set<int>::iterator beg = indices.begin();
1628 for (auto it = std::next(beg); it != indices.end(); ++it)
1629 equal(*beg, *it);
1630 }
1631 return *this;
1632 }
1633
1634 // Restricts lists for list[left..right] to have all equal values.
1635 list &equal_range(int left, int right) {
1636 tgen_ensure(0 <= left and left <= right and right < size_,
1637 "list: range indices must be valid");
1638 for (int i = left; i < right; ++i)
1639 equal(i, i + 1);
1640 return *this;
1641 }
1642
1643 // Restricts lists for all equal elements.
1644 list &all_equal() { return equal_range(0, size_ - 1); }
1645
1646 // Restricts lists for list[S] to be different (distinct), for given subset
1647 // S of indices. You cannot add two of these restrictions on sets that
1648 // intersect.
1649 list &different(std::set<int> indices) {
1650 if (!indices.empty())
1651 diff_restrictions_.push_back(indices);
1652 return *this;
1653 }
1654
1655 // Restricts lists for list[idx_1] != list[idx_2].
1656 list &different(int idx_1, int idx_2) {
1657 std::set<int> indices = {idx_1, idx_2};
1658 return different(indices);
1659 }
1660
1661 // Restricts lists for list[left..right] to have all different values.
1662 list &different_range(int left, int right) {
1663 tgen_ensure(0 <= left and left <= right and right < size_,
1664 "list: range indices must be valid");
1665 std::vector<int> indices(right - left + 1);
1666 std::iota(indices.begin(), indices.end(), left);
1667 return different(std::set<int>(indices.begin(), indices.end()));
1668 }
1669
1670 // Restricts lists for all different elements.
1672 std::vector<int> indices(size_);
1673 std::iota(indices.begin(), indices.end(), 0);
1674 return different(std::set<int>(indices.begin(), indices.end()));
1675 }
1676
1677 // Restricts adjacent list entries to be different: list[i] != list[i+1].
1679 for (int i = 1; i < size_; ++i)
1680 different(i - 1, i);
1681 return *this;
1682 }
1683
1684 // List value.
1685 // Operations on a value are not random.
1687 using tgen_is_sequential_tag = detail::is_sequential_tag;
1688
1689 using value_type = T; // Value type, for templates.
1690 using std_type = std::vector<T>; // std type for value.
1691
1692 std::vector<T> vec_; // list.
1693 char sep_; // Separator for printing.
1694
1695 value(const std::vector<T> &vec) : vec_(vec), sep_(' ') {}
1696 value(const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1697
1698 // Fetches size.
1699 int size() const { return static_cast<int>(vec_.size()); }
1700
1701 // Fetches position idx.
1702 T &operator[](int idx) {
1703 tgen_ensure(0 <= idx and idx < size(),
1704 "list: value: index out of bounds");
1705 return vec_[idx];
1706 }
1707 const T &operator[](int idx) const {
1708 tgen_ensure(0 <= idx and idx < size(),
1709 "list: value: index out of bounds");
1710 return vec_[idx];
1711 }
1712
1713 // Sorts values in non-decreasing order.
1714 // O(n log n).
1716 std::sort(vec_.begin(), vec_.end());
1717 return *this;
1718 }
1719
1720 // Reverses list.
1721 // O(n).
1723 std::reverse(vec_.begin(), vec_.end());
1724 return *this;
1725 }
1726
1727 // Sets the separator for the list, for printing.
1728 // O(1).
1729 value &separator(char sep) {
1730 sep_ = sep;
1731 return *this;
1732 }
1733
1734 // Concatenates two values.
1735 // Linear.
1736 value operator+(const value &rhs) const {
1737 std::vector<T> new_vec = vec_;
1738 for (int i = 0; i < rhs.size(); ++i)
1739 new_vec.push_back(rhs[i]);
1740 return value(new_vec);
1741 }
1742
1743 // Shuffles list uniformly.
1744 // O(n).
1746 for (int i = 0; i < size(); ++i)
1747 std::swap(vec_[i], vec_[next(0, size() - 1)]);
1748 return *this;
1749 }
1750
1751 // Returns a random element uniformly.
1752 // O(1).
1753 T pick() const { return vec_[next<int>(0, size() - 1)]; }
1754
1755 // Returns vec_[i] with probability proportional to distribution[i].
1756 // O(1).
1757 template <typename Dist>
1758 T pick_by_distribution(const std::vector<Dist> &distribution) const {
1759 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
1760 "value and distribution must have the same size");
1761 return vec_[next_by_distribution(distribution)];
1762 }
1763 template <typename Dist>
1764 T pick_by_distribution(
1765 const std::initializer_list<Dist> &distribution) const {
1766 return pick_by_distribution(std::vector<Dist>(distribution));
1767 }
1768
1769 // Chooses k values uniformly, as in a subsequence of size k.
1770 // O(n).
1771 value choose(int k) const {
1772 tgen_ensure(0 < k and k <= size(),
1773 "number of elements to choose must be valid");
1774 std::vector<T> new_vec;
1775 int need = k;
1776 for (int i = 0; need > 0; ++i) {
1777 int left = size() - i;
1778 if (next(1, left) <= need) {
1779 new_vec.push_back(vec_[i]);
1780 need--;
1781 }
1782 }
1783 return value(new_vec);
1784 }
1785
1786 // Prints to std::ostream, separated by sep_.
1787 friend std::ostream &operator<<(std::ostream &out, const value &val) {
1788 for (int i = 0; i < val.size(); ++i) {
1789 if (i > 0)
1790 out << val.sep_;
1791 out << val[i];
1792 }
1793 return out;
1794 }
1795
1796 // Gets a std::vector representing the value.
1797 auto to_std() const {
1798 if constexpr (!detail::is_generator_value<T>::value) {
1799 return vec_;
1800 } else {
1801 std::vector<typename T::std_type> vec;
1802 for (const auto &i : vec_)
1803 vec.push_back(i.to_std());
1804 return vec;
1805 }
1806 }
1807 };
1808
1809 // Generates list value.
1810 // Optimized for performance (unconstrained and all-different fast paths).
1811 // O(n log n).
1812 value gen() const {
1813 if (diff_restrictions_.empty()) {
1814 if (auto unconstrained = try_gen_unconstrained())
1815 return *unconstrained;
1816 }
1817 if (auto all_different = try_gen_all_different())
1818 return *all_different;
1819
1820 ensure_neigh_allocated();
1821 std::vector<T> vec(size_);
1822 std::vector<bool> defined_idx(
1823 size_, false); // For every index, if it has been set in `vec`.
1824
1825 std::vector<int> comp_id(size_, -1); // Component id of each index.
1826 std::vector<std::vector<int>> comp(size_); // Component of each comp-id.
1827 int comp_count = 0; // Number of different components.
1828
1829 // Defines value of entire component.
1830 auto define_comp = [&](int cur_comp, T val) {
1831 for (int idx : comp[cur_comp]) {
1832 tgen_ensure(!defined_idx[idx]);
1833 vec[idx] = val;
1834 defined_idx[idx] = true;
1835 }
1836 };
1837
1838 // Groups = components.
1839 {
1840 std::vector<bool> vis(size_, false); // Visited for each index.
1841 for (int idx = 0; idx < size_; ++idx)
1842 if (!vis[idx]) {
1843 T new_value;
1844 bool value_defined = false;
1845
1846 // BFS to visit the connected component, grouping equal
1847 // values.
1848 std::queue<int> q({idx});
1849 vis[idx] = true;
1850 std::vector<int> component;
1851 while (!q.empty()) {
1852 int cur_idx = q.front();
1853 q.pop();
1854
1855 component.push_back(cur_idx);
1856
1857 // Checks value.
1858 auto [l, r] = val_range_at(cur_idx);
1859 if (l == r) {
1860 if (!value_defined) {
1861 // We found the value.
1862 value_defined = true;
1863 new_value = l;
1864 } else if (new_value != l) {
1865 // We found a contradiction
1866 throw detail::contradiction_error(
1867 "list",
1868 "tried to set value to `" +
1869 std::to_string(new_value) +
1870 "`, but it was already set as `" +
1871 std::to_string(l) + "`");
1872 }
1873 }
1874
1875 for (int nxt_idx : neigh_[cur_idx]) {
1876 if (!vis[nxt_idx]) {
1877 vis[nxt_idx] = true;
1878 q.push(nxt_idx);
1879 }
1880 }
1881 }
1882
1883 // Group entire component, checking if value is defined.
1884 for (int cur_idx : component) {
1885 comp_id[cur_idx] = comp_count;
1886 comp[comp_id[cur_idx]].push_back(cur_idx);
1887 }
1888
1889 // Defines value if needed.
1890 if (value_defined)
1891 define_comp(comp_count, new_value);
1892
1893 ++comp_count;
1894 }
1895 }
1896
1897 // Initial parsing of different restrictions.
1898 std::vector<std::set<int>> diff_containing_comp_idx(comp_count);
1899 {
1900 int dist_id = 0;
1901 for (const std::set<int> &diff : diff_restrictions_) {
1902 // Checks if there are too many different values.
1903 if (static_cast<uint64_t>(diff.size() - 1) +
1904 static_cast<uint64_t>(value_l_) >
1905 static_cast<uint64_t>(value_r_))
1906 throw detail::contradiction_error(
1907 "list", "tried to generate " +
1908 std::to_string(diff.size()) +
1909 " different values, but the maximum is " +
1910 std::to_string(value_r_ - value_l_ + 1));
1911
1912 // Checks if two values in same component are marked as
1913 // different.
1914 std::set<int> comp_ids;
1915 for (int idx : diff) {
1916 if (comp_ids.count(comp_id[idx]))
1917 throw detail::contradiction_error(
1918 "list", "tried to set two indices as equal and "
1919 "different");
1920 comp_ids.insert(comp_id[idx]);
1921
1922 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
1923 }
1924 ++dist_id;
1925 }
1926 }
1927
1928 // If some value is in >= 3 sets, then there is a cycle.
1929 for (auto &diff_containing : diff_containing_comp_idx)
1930 if (diff_containing.size() >= 3)
1931 throw detail::complex_restrictions_error(
1932 "list",
1933 "one index cannot be in >= 3 'different' restrictions");
1934
1935 std::vector<bool> vis_diff(diff_restrictions_.size(), false);
1936 std::vector<bool> initially_defined_comp_idx(comp_count, false);
1937
1938 // Fills the value in a tree defined by "different" restrictions.
1939 auto define_tree = [&](int diff_id) {
1940 // The set `diff_restrictions_[diff_id]` can have some
1941 // values that are defined.
1942
1943 // Generates set of already defined values.
1944 std::set<T> defined_values;
1945 for (int idx : diff_restrictions_[diff_id])
1946 if (defined_idx[idx]) {
1947 // Checks if two values in `diff_restrictions_[dist_id]`
1948 // have been set to the same value
1949 if (defined_values.count(vec[idx]))
1950 throw detail::contradiction_error(
1951 "list",
1952 "tried to set two indices as equal and different");
1953
1954 defined_values.insert(vec[idx]);
1955 }
1956
1957 // Generates values in this root "different" restriction.
1958 {
1959 int new_value_count =
1960 static_cast<int>(diff_restrictions_[diff_id].size()) -
1961 static_cast<int>(defined_values.size());
1962 std::vector<T> generated_values =
1963 generate_distinct_values(new_value_count, defined_values);
1964 auto val_it = generated_values.begin();
1965 for (int idx : diff_restrictions_[diff_id])
1966 if (defined_idx[idx]) {
1967 // The root can cover these components, but there should
1968 // not be any other defined in this tree.
1969 initially_defined_comp_idx[comp_id[idx]] = false;
1970 } else {
1971 define_comp(comp_id[idx], *val_it);
1972 ++val_it;
1973 }
1974 }
1975
1976 // BFS on the tree of "different" restrictions.
1977 std::queue<std::pair<int, int>> q; // {id, parent id}
1978 q.emplace(diff_id, -1);
1979 vis_diff[diff_id] = true;
1980 while (!q.empty()) {
1981 auto [cur_diff, parent] = q.front();
1982 q.pop();
1983
1984 std::set<int> neigh_diff;
1985 for (int idx : diff_restrictions_[cur_diff])
1986 for (int nxt_diff :
1987 diff_containing_comp_idx[comp_id[idx]]) {
1988 if (nxt_diff == cur_diff or nxt_diff == parent)
1989 continue;
1990
1991 // Cycle found.
1992 if (vis_diff[nxt_diff])
1993 throw detail::complex_restrictions_error(
1994 "list",
1995 "cycle found in 'different' restrictions");
1996
1997 neigh_diff.insert(nxt_diff);
1998 }
1999
2000 for (int nxt_diff : neigh_diff) {
2001 vis_diff[nxt_diff] = true;
2002 q.emplace(nxt_diff, cur_diff);
2003
2004 // Generates this "different" restriction.
2005 std::set<T> nxt_defined_values;
2006 for (int idx2 : diff_restrictions_[nxt_diff])
2007 if (defined_idx[idx2]) {
2008 // There cannot be any more defined. This case is
2009 // when there are values not covered by a single
2010 // "different" restriction in the tree.
2011 if (initially_defined_comp_idx[comp_id[idx2]])
2012 throw detail::complex_restrictions_error(
2013 "list");
2014
2015 nxt_defined_values.insert(vec[idx2]);
2016 }
2017 int new_value_count =
2018 static_cast<int>(diff_restrictions_[nxt_diff].size()) -
2019 static_cast<int>(nxt_defined_values.size());
2020 std::vector<T> generated_values = generate_distinct_values(
2021 new_value_count, nxt_defined_values);
2022 auto val_it = generated_values.begin();
2023 for (int idx2 : diff_restrictions_[nxt_diff])
2024 if (!defined_idx[idx2]) {
2025 define_comp(comp_id[idx2], *val_it);
2026 ++val_it;
2027 }
2028 }
2029 }
2030 };
2031
2032 // Loops through "different" restrictions, sorts "different"
2033 // restrictions by number of defined components (non-increasing). This
2034 // guarantees that if there is a valid root (that covers all 'defined'),
2035 // we find it.
2036 {
2037 std::vector<std::pair<int, int>> defined_cnt_and_diff_idx;
2038 int dist_id = 0;
2039 for (const std::set<int> &diff : diff_restrictions_) {
2040 int defined_cnt = 0;
2041 for (int idx : diff)
2042 if (defined_idx[idx]) {
2043 ++defined_cnt;
2044 initially_defined_comp_idx[comp_id[idx]] = true;
2045 }
2046 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2047 ++dist_id;
2048 }
2049
2050 std::sort(defined_cnt_and_diff_idx.rbegin(),
2051 defined_cnt_and_diff_idx.rend());
2052 for (auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2053 if (!vis_diff[diff_idx])
2054 define_tree(diff_idx);
2055 }
2056
2057 // Loops through "different" restrictions do define the rest.
2058 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2059 ++dist_id)
2060 if (!vis_diff[dist_id])
2061 define_tree(static_cast<int>(dist_id));
2062
2063 // Define final values. These values all should be random in [l, r], and
2064 // the "different" restrictions have already been processed. However,
2065 // there can be still equality restrictions, so we define entire
2066 // components.
2067 for (int idx = 0; idx < size_; ++idx)
2068 if (!defined_idx[idx])
2069 define_comp(comp_id[idx], next<T>(value_l_, value_r_));
2070
2071 if (!values_.empty()) {
2072 // Needs to fetch the values from the value set.
2073 std::vector<T> value_vec(values_.begin(), values_.end());
2074 for (T &val : vec)
2075 val = value_vec[val];
2076 }
2077
2078 return value(vec);
2079 }
2080
2081 private:
2082 // Materializes neigh_ after the first equality restriction.
2083 void ensure_neigh_allocated() const {
2084 if (neigh_.size() == static_cast<size_t>(size_))
2085 return;
2086 neigh_.assign(size_, {});
2087 }
2088
2089 // Materializes val_range_ after the first per-index restriction.
2090 void ensure_val_range_materialized() const {
2091 if (!uses_full_range_)
2092 return;
2093 val_range_.assign(size_, {value_l_, value_r_});
2094 uses_full_range_ = false;
2095 }
2096
2097 // Returns the allowed value range at index idx.
2098 std::pair<T, T> val_range_at(int idx) const {
2099 if (uses_full_range_)
2100 return {value_l_, value_r_};
2101 return val_range_[idx];
2102 }
2103
2104 // Generates a uniformly random list of k distinct values in `[value_l,
2105 // value_r]`, such that no value is in `forbidden_values`.
2106 std::vector<T>
2107 generate_distinct_values(int k, const std::set<T> &forbidden_values) const {
2108 for (auto forbidden : forbidden_values)
2109 tgen_ensure(value_l_ <= forbidden and forbidden <= value_r_);
2110 const T num_available =
2111 static_cast<T>((value_r_ - value_l_ + 1) -
2112 static_cast<T>(forbidden_values.size()));
2113 if (num_available < k)
2114 throw detail::complex_restrictions_error(
2115 "list", "not enough distinct values");
2116 if (forbidden_values.empty())
2117 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();
2118
2119 std::map<T, T> virtual_list;
2120 std::vector<T> gen_list;
2121 for (int i = 0; i < k; ++i) {
2122 T ti = static_cast<T>(i);
2123 T j = next<T>(ti, num_available - 1);
2124 T vj = virtual_list.count(j) ? virtual_list[j] : j;
2125 T vi = virtual_list.count(ti) ? virtual_list[ti] : ti;
2126
2127 virtual_list[j] = vi, virtual_list[ti] = vj;
2128
2129 gen_list.push_back(virtual_list[ti]);
2130 }
2131
2132 for (T &val : gen_list)
2133 val += value_l_;
2134
2135 std::vector<std::pair<T, int>> values_sorted;
2136 for (std::size_t i = 0; i < gen_list.size(); ++i)
2137 values_sorted.emplace_back(gen_list[i], i);
2138 std::sort(values_sorted.begin(), values_sorted.end());
2139 auto cur_it = forbidden_values.begin();
2140 int smaller_forbidden_count = 0;
2141 for (auto [val, idx] : values_sorted) {
2142 while (cur_it != forbidden_values.end() and
2143 *cur_it <= val + smaller_forbidden_count)
2144 ++cur_it, ++smaller_forbidden_count;
2145 gen_list[idx] += static_cast<T>(smaller_forbidden_count);
2146 }
2147
2148 return gen_list;
2149 }
2150
2151 // If this generator has no constraints beyond [value_l_, value_r_],
2152 // returns independent uniform samples; otherwise returns std::nullopt.
2153 // O(n).
2154 std::optional<value> try_gen_unconstrained() const {
2155 if (!values_.empty() or index_constraints_)
2156 return std::nullopt;
2157
2158 std::vector<T> vec(size_);
2159 for (int i = 0; i < size_; ++i)
2160 vec[i] = next<T>(value_l_, value_r_);
2161 return value(vec);
2162 }
2163
2164 // If this generator is exactly all-distinct in [value_l_, value_r_],
2165 // returns a uniformly random list; otherwise returns std::nullopt.
2166 // Optimized for performance (distinct_range fast path).
2167 // O(n log n).
2168 std::optional<value> try_gen_all_different() const {
2169 if (!values_.empty() or diff_restrictions_.size() != 1)
2170 return std::nullopt;
2171
2172 const std::set<int> &diff = diff_restrictions_[0];
2173 if (static_cast<int>(diff.size()) != size_ or *diff.begin() != 0 or
2174 *diff.rbegin() != size_ - 1)
2175 return std::nullopt;
2176
2177 if (!neigh_.empty()) {
2178 for (const auto &adj : neigh_) {
2179 if (!adj.empty())
2180 return std::nullopt;
2181 }
2182 }
2183
2184 if (index_constraints_)
2185 return std::nullopt;
2186
2187 if (static_cast<long long>(size_) >
2188 static_cast<long long>(value_r_) - value_l_ + 1)
2189 throw detail::contradiction_error(
2190 "list", "tried to generate " + std::to_string(size_) +
2191 " different values, but the maximum is " +
2192 std::to_string(value_r_ - value_l_ + 1));
2193
2194 return distinct_range<T>(value_l_, value_r_).gen_list(size_);
2195 }
2196};
2197
2198/*******************
2199 * *
2200 * PERMUTATION *
2201 * *
2202 *******************/
2203
2204/*
2205 * Permutation generation.
2206 *
2207 * Permutation are defined always as numbers in [0, n), that is, 0-based.
2208 */
2209
2211 int size_; // Size of permutation.
2212 std::vector<std::pair<int, int>> defs_; // {idx, value}.
2213 std::optional<std::vector<int>> cycle_sizes_; // Cycle sizes.
2214
2215 // Creates generator for permutation of size 'size'.
2216 permutation(int size) : size_(size) {
2217 tgen_ensure(size_ > 0, "permutation: size must be positive");
2218 }
2219
2220 // Restricts permutations for permutation[idx] = val.
2221 permutation &fix(int idx, int val) {
2222 tgen_ensure(0 <= idx and idx < size_,
2223 "permutation: index must be valid");
2224 defs_.emplace_back(idx, val);
2225 return *this;
2226 }
2227
2228 // Restricts permutations for permutation to have cycle sizes.
2229 permutation &cycles(const std::vector<int> &cycle_sizes) {
2231 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),
2232 "permutation: cycle sizes must add up to size of permutation");
2233 cycle_sizes_ = cycle_sizes;
2234 return *this;
2235 }
2236 permutation &cycles(const std::initializer_list<int> &cycle_sizes) {
2237 return cycles(std::vector<int>(cycle_sizes));
2238 }
2239
2240 // Permutation value.
2241 // Operations on a value are not random.
2243 using tgen_is_sequential_tag = detail::is_sequential_tag;
2244
2245 using std_type = std::vector<int>; // std type for value.
2246 std::vector<int> vec_; // Permutation.
2247 char sep_; // Separator for printing.
2248 bool print_1_based_; // If should print values 1-based (print only).
2249
2250 value(const std::vector<int> &vec)
2251 : vec_(vec), sep_(' '), print_1_based_(false) {
2252 tgen_ensure(!vec_.empty(), "permutation: value: cannot be empty");
2253 std::vector<bool> vis(vec_.size(), false);
2254 for (int i = 0; i < size(); ++i) {
2255 tgen_ensure(0 <= vec_[i] and
2256 vec_[i] < static_cast<int>(vec_.size()),
2257 "permutation: value: values must be from `0` to "
2258 "`size-1`");
2259 tgen_ensure(!vis[vec_[i]],
2260 "permutation: value: cannot have repeated values");
2261 vis[vec_[i]] = true;
2262 }
2263 }
2264 value(const std::initializer_list<int> &il)
2265 : value(std::vector<int>(il)) {}
2266
2267 // Fetches size.
2268 int size() const { return static_cast<int>(vec_.size()); }
2269
2270 // Fetches position idx.
2271 const int &operator[](int idx) const {
2272 tgen_ensure(0 <= idx and idx < size(),
2273 "permutation: value: index out of bounds");
2274 return vec_[idx];
2275 }
2276
2277 // Returns parity of the permutation (+1 if even, -1 if odd).
2278 // O(n).
2279 int parity() const {
2280 std::vector<bool> vis(size(), false);
2281 int cycles = 0;
2282
2283 for (int i = 0; i < size(); ++i)
2284 if (!vis[i]) {
2285 ++cycles;
2286 for (int j = i; !vis[j]; j = vec_[j])
2287 vis[j] = true;
2288 }
2289 // Even iff (n - cycles) is even.
2290 return ((size() - cycles) % 2 == 0) ? +1 : -1;
2291 }
2292
2293 // Sorts values in increasing order.
2294 // O(n).
2296 for (int i = 0; i < size(); ++i)
2297 vec_[i] = i;
2298 return *this;
2299 }
2300
2301 // Reverses permutation.
2302 // O(n).
2304 std::reverse(vec_.begin(), vec_.end());
2305 return *this;
2306 }
2307
2308 // Inverse of the permutation.
2309 // O(n).
2311 std::vector<int> inv(size());
2312 for (int i = 0; i < size(); ++i)
2313 inv[vec_[i]] = i;
2314 swap(vec_, inv);
2315 return *this;
2316 }
2317
2318 // Sets the separator, for printing.
2319 // O(1).
2320 value &separator(char sep) {
2321 sep_ = sep;
2322 return *this;
2323 }
2324
2325 // Sets that should print values 1-based. Does not change stored
2326 // values or to_std(); use to_std_1_based() for a 1-based export.
2327 // O(1).
2329 print_1_based_ = true;
2330 return *this;
2331 }
2332
2333 // Shuffles permutation uniformly.
2334 // O(n).
2336 for (int i = 0; i < size(); ++i)
2337 std::swap(vec_[i], vec_[next(0, size() - 1)]);
2338 return *this;
2339 }
2340
2341 // Returns a random element uniformly.
2342 // O(1).
2343 int pick() const { return vec_[next<int>(0, size() - 1)]; }
2344
2345 // Returns vec_[i] with probability proportional to distribution[i].
2346 // O(1).
2347 template <typename Dist>
2348 int pick_by_distribution(const std::vector<Dist> &distribution) const {
2349 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
2350 "value and distribution must have the same size");
2351 return vec_[next_by_distribution(distribution)];
2352 }
2353 template <typename Dist>
2354 int pick_by_distribution(
2355 const std::initializer_list<Dist> &distribution) const {
2356 return pick_by_distribution(std::vector<Dist>(distribution));
2357 }
2358
2359 // Prints to std::ostream, separated by sep_.
2360 friend std::ostream &operator<<(std::ostream &out, const value &val) {
2361 for (int i = 0; i < val.size(); ++i) {
2362 if (i > 0)
2363 out << val.sep_;
2364 out << val[i] + val.print_1_based_;
2365 }
2366 return out;
2367 }
2368
2369 // Gets a std::vector representing the value (0-based). Unaffected by
2370 // print_1_based().
2371 std::vector<int> to_std() const { return std_type(vec_); }
2372
2373 // Gets a 1-based std::vector (each element +1). Unaffected by
2374 // print_1_based().
2375 std::vector<int> to_std_1_based() const {
2376 std::vector<int> out = vec_;
2377 for (int &x : out)
2378 ++x;
2379 return out;
2380 }
2381 };
2382
2383 // Generates permutation value.
2384 // O(n).
2385 value gen() const {
2386 if (!cycle_sizes_) {
2387 // Cycle sizes not specified.
2388 std::vector<int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2389 for (auto [idx, val] : defs_) {
2391 0 <= val and val < size_,
2392 "permutation: value in permutation must be in [0, " +
2393 std::to_string(size_) + ")");
2394
2395 if (idx_to_val[idx] != -1) {
2396 tgen_ensure(idx_to_val[idx] == val,
2397 "permutation: cannot set an index to two "
2398 "different values");
2399 } else
2400 idx_to_val[idx] = val;
2401
2402 if (val_to_idx[val] != -1) {
2403 tgen_ensure(val_to_idx[val] == idx,
2404 "permutation: cannot set two indices to the "
2405 "same value");
2406 } else
2407 val_to_idx[val] = idx;
2408 }
2409
2410 std::vector<int> perm(size_);
2411 std::iota(perm.begin(), perm.end(), 0);
2412 shuffle(perm.begin(), perm.end());
2413 int cur_idx = 0;
2414 for (int &i : idx_to_val)
2415 if (i == -1) {
2416 // While this value is used, skip.
2417 while (val_to_idx[perm[cur_idx]] != -1)
2418 ++cur_idx;
2419 i = perm[cur_idx++];
2420 }
2421 return idx_to_val;
2422 }
2423
2424 // Creates cycles.
2425 std::vector<int> order(size_);
2426 std::iota(order.begin(), order.end(), 0);
2427 shuffle(order.begin(), order.end());
2428 int idx = 0;
2429 std::vector<std::vector<int>> cycles;
2430 for (int cycle_size : *cycle_sizes_) {
2431 cycles.emplace_back();
2432 for (int i = 0; i < cycle_size; ++i)
2433 cycles.back().push_back(order[idx++]);
2434 }
2435
2436 // Retrieves permutation from cycles.
2437 std::vector<int> perm(size_, -1);
2438 for (const std::vector<int> &cycle : cycles) {
2439 int cur_size = static_cast<int>(cycle.size());
2440 for (int i = 0; i < cur_size; ++i)
2441 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2442 }
2443
2444 return value(perm);
2445 }
2446};
2447
2448/************
2449 * *
2450 * MATH *
2451 * *
2452 ************/
2453
2454namespace math {
2455
2456namespace detail {
2457
2458using namespace tgen::detail;
2459
2460inline int popcount(uint64_t x) { return __builtin_popcountll(x); }
2461
2462inline int ctzll(uint64_t x) {
2463 // Mystery code found on the internet.
2464 // Uses de Bruijn sequence.
2465 static const unsigned char index64[64] = {
2466 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2467 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2468 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2469 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2470 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2471}
2472
2473inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2474 return static_cast<uint64_t>(static_cast<u128>(a) * b % m);
2475}
2476
2477// O(log n).
2478// 0 <= x < m.
2479inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2480 if (!y)
2481 return 1;
2482 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2483 return y % 2 ? mul_mod(x, ans, m) : ans;
2484}
2485
2486} // namespace detail
2487
2488// O(log^2 n).
2489inline bool is_prime(uint64_t n) {
2490 if (n < 2)
2491 return false;
2492 if (n == 2 or n == 3)
2493 return true;
2494 if (n % 2 == 0)
2495 return false;
2496
2497 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2498 // These bases are guaranteed to work for n <= 2^64.
2499 for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2500 uint64_t x = detail::expo_mod(a, d, n);
2501 if (x == 1 or x == n - 1 or a % n == 0)
2502 continue;
2503
2504 for (uint64_t j = 0; j < r - 1; ++j) {
2505 x = detail::mul_mod(x, x, n);
2506 if (x == n - 1)
2507 break;
2508 }
2509 if (x != n - 1)
2510 return false;
2511 }
2512 return true;
2513}
2514
2515namespace detail {
2516
2517inline uint64_t pollard_rho(uint64_t n) {
2518 if (n == 1 or is_prime(n))
2519 return n;
2520 auto f = [n](uint64_t x) { return mul_mod(x, x, n) + 1; };
2521
2522 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2523 while (t % 40 != 0 or std::gcd(prd, n) == 1) {
2524 if (x == y)
2525 x = ++x0, y = f(x);
2526 q = mul_mod(prd, x > y ? x - y : y - x, n);
2527 if (q != 0)
2528 prd = q;
2529 x = f(x), y = f(f(y)), ++t;
2530 }
2531 return std::gcd(prd, n);
2532}
2533
2534inline std::vector<uint64_t> factor(uint64_t n) {
2535 if (n == 1)
2536 return {};
2537 if (is_prime(n))
2538 return {n};
2539 uint64_t d = pollard_rho(n);
2540 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2541 l.insert(l.end(), r.begin(), r.end());
2542 return l;
2543}
2544
2545// Error handling.
2546template <typename T>
2547std::runtime_error there_is_no_in_range_error(const std::string &type, T l,
2548 T r) {
2549 return error("math: there is no " + type + " in range [" +
2550 std::to_string(l) + ", " + std::to_string(r) + "]");
2551}
2552template <typename T>
2553std::runtime_error there_is_no_from_error(const std::string &type, T r) {
2554 return error("math: there is no " + type + " from " + std::to_string(r));
2555}
2556template <typename T>
2557std::runtime_error there_is_no_upto_error(const std::string &type, T r) {
2558 return error("math: there is no " + type + " up to " + std::to_string(r));
2559}
2560
2561// O(log mod).
2562// 0 < a < mod.
2563// gcd(a, mod) = 1.
2564inline i128 modular_inverse_128(i128 a, i128 mod) {
2565 tgen_ensure(0 < a and a < mod,
2566 "math: modular inverse requires 0 < value < mod");
2567
2568 i128 t = 0, new_t = 1;
2569 i128 r = mod, new_r = a;
2570
2571 while (new_r != 0) {
2572 i128 q = r / new_r;
2573
2574 auto tmp_t = t - q * new_t;
2575 t = new_t;
2576 new_t = tmp_t;
2577
2578 auto tmp_r = r - q * new_r;
2579 r = new_r;
2580 new_r = tmp_r;
2581 }
2582
2583 tgen_ensure(r == 1, "math: remainder and mod must be coprime");
2584
2585 if (t < 0)
2586 t += mod;
2587 return t;
2588}
2589
2590// checks if a * b <= limit, for positive numbers.
2591inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2592 if (a == 0 or b == 0)
2593 return true;
2594 return a <= limit / b;
2595}
2596
2597// base^exp, or null if base^exp > limit.
2598inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2599 uint64_t limit) {
2600 uint64_t result = 1;
2601
2602 while (exp) {
2603 if (exp & 1) {
2604 if (!mul_leq(result, base, limit))
2605 return std::nullopt;
2606 result *= base;
2607 }
2608
2609 exp >>= 1;
2610 // Necessary for correctness.
2611 if (!exp)
2612 break;
2613
2614 if (!mul_leq(base, base, limit))
2615 return std::nullopt;
2616 base *= base;
2617 }
2618 return result;
2619}
2620
2621// O(log n log k).
2622// 0 < k.
2623inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2624 tgen_ensure_against_bug(k > 0, "math: value must be valid");
2625 if (k == 1 or n <= 1)
2626 return n;
2627
2628 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2629
2630 while (lo < hi) {
2631 uint64_t mid = lo + (hi - lo + 1) / 2;
2632
2633 if (expo(mid, k, n)) {
2634 lo = mid;
2635 } else {
2636 hi = mid - 1;
2637 }
2638 }
2639 return lo;
2640}
2641
2642// gcd(a, b).
2643// O(log a).
2644inline i128 gcd128(i128 a, i128 b) {
2645 if (a < 0)
2646 a = -a;
2647 if (b < 0)
2648 b = -b;
2649 while (b != 0) {
2650 i128 t = a % b;
2651 a = b;
2652 b = t;
2653 }
2654 return a;
2655}
2656
2657// min(2^64, a*b).
2658// O(log a).
2659// a, b >= 0.
2660inline i128 mul_saturate(i128 a, i128 b) {
2661 tgen_ensure(a >= 0 and b >= 0);
2662 static const i128 LIMIT = static_cast<i128>(1) << 64;
2663 if (a == 0 or b == 0)
2664 return 0;
2665 if (a > LIMIT / b)
2666 return LIMIT;
2667 return a * b;
2668}
2669
2670struct crt {
2671 using T = i128;
2672 T a, m;
2673
2674 crt() : a(0), m(1) {}
2675 crt(T a_, T m_) : a(a_), m(m_) {}
2676 crt operator*(crt C) {
2677 if (m == 0 or C.m == 0)
2678 return {-1, 0};
2679
2680 T g = gcd128(m, C.m);
2681 if ((C.a - a) % g != 0)
2682 return {-1, 0};
2683
2684 T m1 = m / g;
2685 T m2 = C.m / g;
2686
2687 if (m2 == 1)
2688 return {a, m};
2689
2690 T inv = modular_inverse_128(m1 % m2, m2);
2691
2692 T k = ((C.a - a) / g) % m2;
2693 if (k < 0)
2694 k += m2;
2695
2696 k = static_cast<u128>(k) * inv % m2;
2697
2698 T lcm = mul_saturate(m, m2);
2699
2700 T res = (a + static_cast<T>((static_cast<u128>(k) * m) % lcm)) % lcm;
2701 if (res < 0)
2702 res += lcm;
2703
2704 return {res, lcm};
2705 }
2706};
2707
2708// Math hacks to operate on log space.
2709
2710inline constexpr long double LOG_ZERO = -INFINITY;
2711inline constexpr long double LOG_ONE = 0.0;
2712
2713inline long double log_space(long double x) {
2714 return x == 0.0 ? LOG_ZERO : std::log(x);
2715}
2716
2717// Math hack to add two values in log space.
2718inline long double add_log_space(long double a, long double b) {
2719 if (a < b)
2720 std::swap(a, b);
2721 if (b == LOG_ZERO)
2722 return a;
2723 return a + std::log1p(std::exp(static_cast<double>(b - a)));
2724}
2725
2726// Math hack to subtract two values in log space.
2727// a >= b.
2728inline long double sub_log_space(long double a, long double b) {
2729 if (b >= a)
2730 return LOG_ZERO;
2731 if (b == LOG_ZERO)
2732 return a;
2733 return a + std::log1p(-std::exp(static_cast<double>(b - a)));
2734}
2735
2736} // namespace detail
2737
2738// Sorted.
2739// O(n^(1/4) log n) expected.
2740// 0 < n.
2741inline std::vector<uint64_t> factor(uint64_t n) {
2742 tgen_ensure(n > 0, "math: number to factor must be positive");
2743 auto factors = detail::factor(n);
2744 std::sort(factors.begin(), factors.end());
2745 return factors;
2746}
2747
2748// Sorted.
2749// O(n^(1/4) log n) expected.
2750// 0 < n.
2751inline std::vector<std::pair<uint64_t, int>> factor_by_prime(uint64_t n) {
2752 tgen_ensure(n > 0, "math: number to factor must be positive");
2753 std::vector<std::pair<uint64_t, int>> primes;
2754 for (uint64_t p : factor(n)) {
2755 if (!primes.empty() and primes.back().first == p)
2756 ++primes.back().second;
2757 else
2758 primes.emplace_back(p, 1);
2759 }
2760 return primes;
2761}
2762
2763// O(log mod).
2764// 0 < a < mod.
2765// gcd(a, mod) = 1.
2766inline uint64_t modular_inverse(uint64_t a, uint64_t mod) {
2767 return static_cast<uint64_t>(detail::modular_inverse_128(a, mod));
2768}
2769
2770// O(n^(1/4) log n) expected.
2771// 0 < n.
2772inline uint64_t totient(uint64_t n) {
2773 tgen_ensure(n > 0, "math: totient(0) is undefined");
2774 uint64_t phi = n;
2775
2776 for (auto [p, e] : factor_by_prime(n))
2777 phi -= phi / p;
2778
2779 return phi;
2780}
2781
2782// Returns `(p_i, g_i)`: `p_i` is the prime, `g_i` is the gap.
2783inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
2784prime_gaps() {
2785 // From https://en.wikipedia.org/wiki/Prime_gap.
2786 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
2787 /* clang-format off */ {
2788 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
2789 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
2790 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
2791 191912783, 387096133, 436273009, 1294268491, 1453168141,
2792 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
2793 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
2794 241160624143, 297501075799, 303371455241, 304599508537,
2795 416608695821, 461690510011, 614487453523, 738832927927,
2796 1346294310749, 1408695493609, 1968188556461, 2614941710599,
2797 7177162611713, 13829048559701, 19581334192423, 42842283925351,
2798 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
2799 1686994940955803, 1693182318746371, 43841547845541059,
2800 55350776431903243, 80873624627234849, 203986478517455989,
2801 218034721194214273, 305405826521087869, 352521223451364323,
2802 401429925999153707, 418032645936712127, 804212830686677669,
2803 1425172824437699411, 5733241593241196731, 6787988999657777797
2804 }, /* clang-format on */
2805 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
2806 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
2807 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
2808 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
2809 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
2810 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
2811 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
2812
2813 return value;
2814}
2815
2816// Returns pair (first_composite_in_gap, last_composite_in_gap).
2817// O(log(right)) approximately.
2818inline std::pair<uint64_t, uint64_t> prime_gap_upto(uint64_t right) {
2819 if (right < 4)
2820 throw detail::there_is_no_upto_error("prime gap", right);
2821
2822 const auto &[P, G] = prime_gaps();
2823 for (int i = static_cast<int>(P.size()) - 1;; --i) {
2824 if (P[i] >= right)
2825 continue;
2826
2827 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
2828 uint64_t prev = i > 0 ? G[i - 1] : 0;
2829 uint64_t curr = real_right - P[i];
2830
2831 if (curr >= prev)
2832 return {P[i] + 1, real_right};
2833 }
2834}
2835
2836// From https://oeis.org/A002182/b002182.txt.
2838 /* clang-format off */
2839 static const std::vector<uint64_t> highly_composites = {
2840 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
2841 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
2842 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
2843 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
2844 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
2845 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
2846 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
2847 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
2848 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
2849 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
2850 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
2851 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
2852 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
2853 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
2854 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
2855 26985313555200, 27949074753600, 32607253879200, 46581791256000,
2856 48910880818800, 55898149507200, 65214507758400, 93163582512000,
2857 97821761637600, 130429015516800, 195643523275200, 260858031033600,
2858 288807105787200, 391287046550400, 577614211574400, 782574093100800,
2859 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
2860 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
2861 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
2862 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
2863 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
2864 72779390658374400, 74801040398884800, 106858629141264000,
2865 112201560598327200, 149602080797769600, 224403121196654400,
2866 299204161595539200, 374005201994424000, 448806242393308800,
2867 673209363589963200, 748010403988848000, 897612484786617600,
2868 1122015605983272000, 1346418727179926400, 1795224969573235200,
2869 2244031211966544000, 2692837454359852800, 3066842656354276800,
2870 4381203794791824000, 4488062423933088000, 6133685312708553600,
2871 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
2872 15334213281771384000ULL, 18401055938125660800ULL}; /* clang-format on */
2873 return highly_composites;
2874}
2875
2876// O(log(right)) approximately.
2877inline uint64_t highly_composite_upto(uint64_t right) {
2878 for (int i = static_cast<int>(highly_composites().size()) - 1; i >= 0; --i)
2879 if (highly_composites()[i] <= right)
2880 return highly_composites()[i];
2881
2882 throw detail::there_is_no_upto_error("highly composite number", right);
2883}
2884
2885// O(log^3 (right)) expected.
2886// Generates a random prime in [left, right].
2887inline uint64_t gen_prime(uint64_t left, uint64_t right) {
2888 if (right < left or right < 2)
2889 throw detail::there_is_no_in_range_error("prime", left, right);
2890 left = std::max<uint64_t>(left, 2);
2891 auto [l_gap, r_gap] = prime_gap_upto(right);
2892 if (right - left + 1 <= r_gap - l_gap + 1) {
2893 // There might be no primes in the range.
2894 std::vector<uint64_t> vals(right - left + 1);
2895 iota(vals.begin(), vals.end(), left);
2896 shuffle(vals.begin(), vals.end());
2897 for (uint64_t i : vals)
2898 if (is_prime(i))
2899 return i;
2900 throw detail::there_is_no_in_range_error("prime", left, right);
2901 }
2902
2903 uint64_t n;
2904 do {
2905 n = next(left, right);
2906 } while (!is_prime(n));
2907 return n;
2908}
2909
2910// O(log^3 (left)) expected.
2911// left <= 2^64 - 59.
2912inline uint64_t prime_from(uint64_t left) {
2913 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
2914 "math: invalid bound");
2915 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
2916 if (is_prime(i))
2917 return i;
2918}
2919
2920// O(log^3 (right)) expected.
2921inline uint64_t prime_upto(uint64_t right) {
2922 if (right >= 2)
2923 for (uint64_t i = right; i >= 2; --i)
2924 if (is_prime(i))
2925 return i;
2926 throw detail::there_is_no_upto_error("prime", right);
2927}
2928
2929// O(n^(1/4) log n) expected.
2930// 0 < n.
2931inline int num_divisors(uint64_t n) {
2932 int divisors = 1;
2933 for (auto [p, e] : factor_by_prime(n))
2934 divisors *= (e + 1);
2935 return divisors;
2936}
2937
2938// Random number in [left, right] with `divisor_count` divisors.
2939// O(log(right) log(divisor_count)).
2940// divisor_count must be prime.
2941inline uint64_t gen_divisor_count(uint64_t left, uint64_t right,
2942 int divisor_count) {
2943 tgen_ensure(divisor_count > 0 and is_prime(divisor_count),
2944 "math: divisor count must be prime");
2945 int root = divisor_count - 1;
2946 uint64_t lo = detail::kth_root_floor(left, root);
2947 if (*detail::expo(lo, root, left) < left)
2948 ++lo;
2949 uint64_t p = gen_prime(lo, detail::kth_root_floor(right, root));
2950 return *detail::expo(p, root, right);
2951}
2952
2953// O(|mods| + log (right)).
2954// |rems| = |mods|.
2955// rems_i < mods_i.
2956inline uint64_t gen_congruent(uint64_t left, uint64_t right,
2957 std::vector<uint64_t> rems,
2958 std::vector<uint64_t> mods) {
2959 if (left > right)
2960 throw detail::there_is_no_in_range_error("congruent number", left,
2961 right);
2962 tgen_ensure(rems.size() == mods.size(),
2963 "math: number of remainders and mods must be the same");
2964 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
2965
2966 detail::crt crt;
2967 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
2968 tgen_ensure(rems[i] < mods[i],
2969 "math: remainder must be smaller than the mod");
2970 crt = crt * detail::crt(rems[i], mods[i]);
2971
2972 if (crt.a == -1)
2973 throw detail::there_is_no_in_range_error("congruent number", left,
2974 right);
2975 if (crt.m > right) {
2976 if (!(left <= crt.a and crt.a <= right))
2977 throw detail::there_is_no_in_range_error("congruent number",
2978 left, right);
2979
2980 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
2981 if (crt.a % mods[j] != rems[j])
2982 throw detail::there_is_no_in_range_error("congruent number",
2983 left, right);
2984 return static_cast<uint64_t>(crt.a);
2985 }
2986 }
2987
2988 uint64_t k_min =
2989 crt.a >= left
2990 ? 0
2991 : static_cast<uint64_t>(((left - crt.a) + crt.m - 1) / crt.m);
2992 uint64_t k_max = static_cast<uint64_t>((right - crt.a) / crt.m);
2993
2994 if (k_min > k_max)
2995 throw detail::there_is_no_in_range_error("congruent number", left,
2996 right);
2997
2998 return static_cast<uint64_t>(crt.a + next(k_min, k_max) * crt.m);
2999}
3000
3001// O(log (right)).
3002// rem < mod.
3003inline uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem,
3004 uint64_t mod) {
3005 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
3006 std::vector<uint64_t>({mod}));
3007}
3008
3009// First congruent number >= left.
3010// O(|mods| + log (left)).
3011// |rems| = |mods|.
3012// rems_i < mods_i.
3013inline uint64_t congruent_from(uint64_t left, std::vector<uint64_t> rems,
3014 std::vector<uint64_t> mods) {
3015 tgen_ensure(rems.size() == mods.size(),
3016 "math: number of remainders and mods must be the same");
3017 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3018
3019 detail::crt crt;
3020 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3021 tgen_ensure(rems[i] < mods[i],
3022 "math: remainder must be smaller than the mod");
3023 crt = crt * detail::crt(rems[i], mods[i]);
3024
3025 if (crt.a == -1)
3026 throw detail::there_is_no_from_error("congruent number", left);
3027 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3028 if (crt.a < left)
3029 throw detail::error(
3030 "math: congruent number does not exist or is too large");
3031
3032 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3033 if (crt.a % mods[j] != rems[j])
3034 throw detail::error("math: congruent number does "
3035 "not exist or is too large");
3036 return static_cast<uint64_t>(crt.a);
3037 }
3038 }
3039
3040 uint64_t k = 0;
3041 if (crt.a < left)
3042 k = static_cast<uint64_t>(((left - crt.a) + crt.m - 1) / crt.m);
3043 detail::i128 result = crt.a + k * crt.m;
3044
3045 if (result > std::numeric_limits<uint64_t>::max())
3046 throw detail::error("math: congruent number is too large");
3047 return static_cast<uint64_t>(result);
3048}
3049
3050// O(log (left))
3051// rem < mod.
3052inline uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod) {
3053 return congruent_from(left, std::vector<uint64_t>{rem},
3054 std::vector<uint64_t>{mod});
3055}
3056
3057// Last congruent number <= right.
3058// O(|mods| + log (right)).
3059// |rems| = |mods|.
3060// rems_i < mods_i.
3061inline uint64_t congruent_upto(uint64_t right, std::vector<uint64_t> rems,
3062 std::vector<uint64_t> mods) {
3063 tgen_ensure(rems.size() == mods.size(),
3064 "math: number of remainders and mods must be the same");
3065 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3066
3067 detail::crt crt;
3068 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3069 tgen_ensure(rems[i] < mods[i],
3070 "math: remainder must be smaller than the mod");
3071
3072 crt = crt * detail::crt(rems[i], mods[i]);
3073
3074 if (crt.a == -1)
3075 throw detail::there_is_no_upto_error("congruent number", right);
3076 if (crt.m > right) {
3077 if (!(crt.a <= right))
3078 throw detail::there_is_no_upto_error("congruent number", right);
3079
3080 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3081 if (crt.a % mods[j] != rems[j])
3082 throw detail::there_is_no_upto_error("congruent number",
3083 right);
3084 return static_cast<uint64_t>(crt.a);
3085 }
3086 }
3087
3088 if (crt.a > right)
3089 throw detail::there_is_no_upto_error("congruent number", right);
3090
3091 uint64_t k = static_cast<uint64_t>((right - crt.a) / crt.m);
3092 detail::i128 result = crt.a + k * crt.m;
3093
3094 if (result < 0)
3095 throw detail::there_is_no_upto_error("congruent number", right);
3096 return static_cast<uint64_t>(result);
3097}
3098
3099// O(log r)
3100// rem < mod.
3101inline uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod) {
3102 return congruent_upto(right, std::vector<uint64_t>{rem},
3103 std::vector<uint64_t>{mod});
3104}
3105
3106// Mod used for FFT/NTT.
3107inline constexpr int FFT_MOD = 998244353;
3108
3109// Fibonacci sequence up to 2^64.
3110inline const std::vector<uint64_t> &fibonacci() {
3111 static const std::vector<uint64_t> fib = [] {
3112 std::vector<uint64_t> v = {0, 1};
3113 while (v.back() <=
3114 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3115 v.push_back(v.back() + v[v.size() - 2]);
3116 return v;
3117 }();
3118 return fib;
3119}
3120
3121// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3122// O(n).
3123// 0 < n.
3124// 0 < part_left.
3125inline std::vector<int>
3126gen_partition(int n, int part_left = 1,
3127 std::optional<int> part_right = std::nullopt) {
3128 if (!part_right.has_value())
3129 part_right = n;
3130 part_right = std::min(*part_right, n);
3131 tgen_ensure(n > 0 and part_left > 0,
3132 "math: invalid parameters to gen_partition");
3133 tgen_ensure(part_left <= n and *part_right > 0, "math: no such partition");
3134
3135 // dp[i] = log(number of ways to add to i).
3136 std::vector<long double> dp(n + 1, detail::LOG_ZERO);
3137 dp[0] = detail::LOG_ONE;
3138 long double window = detail::LOG_ZERO;
3139 for (int i = 1; i <= n; ++i) {
3140 if (i >= part_left)
3141 window = detail::add_log_space(window, dp[i - part_left]);
3142 if (i >= *part_right + 1)
3143 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3144 dp[i] = window;
3145 }
3146 tgen_ensure(dp[n] >= 0, "math: no such partition");
3147
3148 // Crazy math tricks ahead.
3149 auto dp_pref = dp;
3150 for (int i = 1; i <= n; ++i)
3151 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3152
3153 std::vector<int> part;
3154 int sum = n;
3155 while (sum > 0) {
3156 // Will generate a number such that what remains is in [l, r].
3157 int l = std::max(0, sum - *part_right), r = sum - part_left;
3158 detail::tgen_ensure_against_bug(r >= 0, "math: r < 0 in gen_partition");
3159
3160 int nxt_sum = std::min(sum, r);
3161 long double random = next<long double>(0, 1);
3162
3163 // We generate a value X (log space), and then choose nxt_sum such
3164 // that dp_pref[nxt_sum-1] < X <= dp_pref[nxt_sum].
3165
3166 // Math hack:
3167 // Let A = pref[l-1], B = pref[r], U = rand().
3168 // X = log[exp(A) + U * (exp(B) - exp(A))]
3169 // = log{exp(B) * [exp(A) / exp(B) + U * (1 - exp(A) / exp(B))]}
3170 // = B + log[exp(A - B) + U - U * exp(A - B))]
3171 // = B + log[U + (1 - U) * exp(A - B)].
3172 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3173 val_r = dp_pref[r];
3174 while (nxt_sum > l and
3175 dp_pref[nxt_sum - 1] >=
3176 val_r +
3177 detail::log_space(
3178 random + (1 - random) * std::exp(static_cast<double>(
3179 val_l - val_r))))
3180 --nxt_sum;
3181
3182 part.push_back(sum - nxt_sum);
3183 sum = nxt_sum;
3184 }
3185
3186 return part;
3187}
3188
3189// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3190// O(n) time/memory if part_right is not set, O(n * k) time/memory otherwise.
3191// 0 < k <= n.
3192// 0 <= part_left.
3193inline std::vector<int>
3194gen_partition_fixed_size(int n, int k, int part_left = 0,
3195 std::optional<int> part_right = std::nullopt) {
3196 if (!part_right.has_value())
3197 part_right = n;
3198 part_right = std::min(*part_right, n);
3199 tgen_ensure(0 < k and k <= n and part_left >= 0,
3200 "math: invalid parameters to gen_partition_fixed_size");
3201 tgen_ensure(static_cast<long long>(k) * part_left <= n and
3202 n <= static_cast<long long>(k) * (*part_right),
3203 "math: no such partition");
3204
3205 // What we need to distribute to the parts.
3206 int s = n - k * part_left;
3207
3208 std::vector<int> part(k);
3209 if (*part_right == n) {
3210 // Stars and bars - O(n).
3211 std::vector<int> cuts = {-1};
3212
3213 int total = s + k - 1, bars = k - 1;
3214 for (int i = 0; i < total and bars > 0; ++i)
3215 if (next<long double>(0, 1) <
3216 static_cast<long double>(bars) / (total - i)) {
3217 cuts.push_back(i);
3218 --bars;
3219 }
3220 cuts.push_back(total);
3221
3222 // Recovers parts.
3223 for (int i = 0; i < k; ++i)
3224 part[i] = cuts[i + 1] - cuts[i] - 1;
3225 } else {
3226 // DP with log trick - O(nk).
3227 int u = *part_right - part_left;
3228
3229 // dp[i][j] = log(#ways to fill i parts with sum j)
3230 std::vector<std::vector<long double>> dp(
3231 k + 1, std::vector<long double>(s + 1, detail::LOG_ZERO));
3232 dp[0][0] = detail::LOG_ONE;
3233
3234 for (int i = 1; i <= k; ++i) {
3235 std::vector<long double> pref = dp[i - 1];
3236 for (int j = 1; j <= s; ++j)
3237 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3238
3239 for (int j = 0; j <= s; ++j) {
3240 dp[i][j] = pref[j];
3241 if (j >= u + 1)
3242 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3243 }
3244 }
3245
3246 // Recovers parts backwards.
3247 int left_to_distribute = s;
3248 for (int i = k; i >= 1; --i) {
3249 long double log_total = detail::LOG_ZERO;
3250 for (int j = 0; j <= u and j <= left_to_distribute; ++j)
3251 log_total = detail::add_log_space(
3252 log_total, dp[i - 1][left_to_distribute - j]);
3253 detail::tgen_ensure_against_bug(
3254 log_total != detail::LOG_ZERO,
3255 "math: total == 0 in gen_partition_fixed_size");
3256
3257 // Now we choose a number with probability proportional to
3258 // dp[i-1][.].
3259
3260 // log(rand() * total) = log(rand()) + log(total).
3261 long double random =
3262 detail::log_space(next<long double>(0, 1)) + log_total;
3263
3264 long double cur_prob = detail::LOG_ZERO;
3265 int chosen = 0;
3266 for (int j = 0; j <= u and j <= left_to_distribute; ++j) {
3267 cur_prob = detail::add_log_space(
3268 cur_prob, dp[i - 1][left_to_distribute - j]);
3269 if (random < cur_prob) {
3270 chosen = j;
3271 break;
3272 }
3273 }
3274
3275 part[k - i] = chosen;
3276 left_to_distribute -= chosen;
3277 }
3278 }
3279
3280 for (int &i : part)
3281 i += part_left;
3282 return part;
3283}
3284
3285// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3286// Inspired by jngen rndm.partition: random delimiters, sort, gap recovery;
3287// omits jngen's part reordering, shuffles, and two-pass redistribution.
3288// 0 < k <= n.
3289// 0 <= part_left.
3290// Not uniformly random; optimized for speed.
3291// O(k log k).
3293 uint64_t n, int k, uint64_t part_left = 0,
3294 std::optional<uint64_t> part_right = std::nullopt) {
3295 if (!part_right.has_value())
3296 part_right = n;
3297 part_right = std::min(*part_right, n);
3298
3299 detail::u128 n128 = n;
3300 detail::u128 k128 = k;
3301 detail::u128 part_left128 = part_left;
3302 detail::u128 part_right128 = *part_right;
3303
3304 tgen_ensure(k > 0 and k128 <= n128,
3305 "math: invalid parameters to gen_partition_fixed_size_fast");
3306 tgen_ensure(part_right128 >= part_left128 and
3307 k128 * part_left128 <= n128 and
3308 k128 * part_right128 >= n128,
3309 "math: no such partition");
3310
3311 uint64_t slack_total = static_cast<uint64_t>(n128 - k128 * part_left128);
3312 uint64_t slack_max = static_cast<uint64_t>(part_right128 - part_left128);
3313
3314 std::vector<uint64_t> part(k);
3315 if (k == 1) {
3316 part[0] = slack_total;
3317 } else {
3318 std::vector<uint64_t> cuts(k - 1);
3319 for (uint64_t &d : cuts)
3320 d = next<uint64_t>(0, slack_total);
3321 std::sort(cuts.begin(), cuts.end());
3322
3323 uint64_t prev = 0;
3324 for (int i = 0; i + 1 < k; ++i) {
3325 part[i] = cuts[i] - prev;
3326 prev = cuts[i];
3327 }
3328 part[k - 1] = slack_total - prev;
3329 }
3330
3331 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3332 detail::u128 val = x + part_left;
3333 detail::tgen_ensure_against_bug(
3334 val <= std::numeric_limits<uint64_t>::max(),
3335 "math: part + part_left exceeds uint64_t in "
3336 "gen_partition_fixed_size_fast");
3337 return static_cast<uint64_t>(val);
3338 };
3339
3340 if (slack_max >= slack_total) {
3341 for (uint64_t &x : part)
3342 x = add_part_left(x);
3343 return part;
3344 }
3345
3346 detail::u128 remaining = 0;
3347 for (uint64_t &x : part) {
3348 if (x > slack_max) {
3349 remaining += x - slack_max;
3350 x = slack_max;
3351 }
3352 x = add_part_left(x);
3353 }
3354
3355 if (remaining > 0) {
3356 for (uint64_t &x : part) {
3357 if (x < *part_right && remaining > 0) {
3358 detail::u128 room = *part_right - x;
3359 detail::u128 add = std::min(remaining, room);
3360 detail::u128 val = x + add;
3361 detail::tgen_ensure_against_bug(
3362 val <= *part_right,
3363 "math: part exceeds part_right after redistribution in "
3364 "gen_partition_fixed_size_fast");
3365 x = static_cast<uint64_t>(val);
3366 remaining -= add;
3367 }
3368 }
3369 detail::tgen_ensure_against_bug(
3370 remaining == 0, "math: remaining mass after redistribution in "
3371 "gen_partition_fixed_size_fast");
3372 }
3373
3374 return part;
3375}
3376
3377// Random partition of elements into k ordered groups (input order preserved).
3378// If max_size is unset, part sizes are uniform via gen_partition_fixed_size.
3379// If max_size is set, uses gen_partition_fixed_size_fast (not uniform).
3380// O(n) if max_size is unset; O(n + k log k) if max_size is set.
3381template <typename T>
3382std::vector<std::vector<T>>
3383partition_elements(std::vector<T> elements, int k, int min_size = 0,
3384 std::optional<uint64_t> max_size = std::nullopt) {
3385 size_t n = elements.size();
3386 tgen_ensure(k > 0, "math: partition_elements: k must be positive");
3387 tgen_ensure(min_size >= 0,
3388 "math: partition_elements: min_size must be non-negative");
3389
3390 std::vector<uint64_t> sizes;
3391 if (max_size.has_value()) {
3392 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3393 } else {
3394 for (int sz :
3395 gen_partition_fixed_size(static_cast<int>(n), k, min_size))
3396 sizes.push_back(sz);
3397 }
3398
3399 std::vector<std::vector<T>> groups;
3400 groups.reserve(k);
3401 size_t pos = 0;
3402 for (uint64_t sz : sizes) {
3403 groups.emplace_back(elements.begin() + pos,
3404 elements.begin() + pos + sz);
3405 pos += sz;
3406 }
3407 return groups;
3408}
3409
3410}; // namespace math
3411
3412/**************
3413 * *
3414 * STRING *
3415 * *
3416 **************/
3417
3418namespace detail {
3419
3420/*
3421 * Regex.
3422 *
3423 * Compatible with testlib's regex.
3424 *
3425 * Operations:
3426 * - A single character yields itself ("a", "3").
3427 * - A list of characters inside square braces yields any a random element
3428 * from the list ("[abc123]").
3429 * - A range of characters is equivalent to listing them ("[a-z1-9A-Z]").
3430 * - A pattern followed by {n} yields the pattern repeated n times ("a{3}").
3431 * - A pattern followed by {l,r} yields the pattern repeated between l and r
3432 * times, uniformly at random ("a{3,5}").
3433 * - A list of patterns separated by | yields a random pattern from the
3434 * list, uniformly at random ("abc|def|ghi").
3435 * - Parentheses can be used for grouping ("a((a|b){3})").
3436 *
3437 * Examples:
3438 * 1. str("[1-9][0-9]{1,2}") generates two- or three-digit numbers.
3439 * 2. str("a[b-d]{2}|e") generates "e" or a random string of length 3, with
3440 * the first character being 'a' and the second and
3441 * third characters being 'b', 'c', or 'd'.
3442 * 3. str("[1-9][0-9]{%d}", n-1) generates n-digit numbers.
3443 *
3444 * Operations defined by {n} and {l,r} are applied from left to right, and
3445 * the pattern that comes before has its delimiters defined either by () or
3446 * [] at its end or is taken from the beginning of the pattern (in
3447 * "a[bc]{2}", "{2}" is applied to "[bc]", and in "[01]abc{3}", the "{3}" is
3448 * applied to "[01]abc").
3449 */
3450
3451// If it has children, it is either a SEQ or an OR group, defined by the
3452// pattern_ field.
3453struct regex_node {
3454 // Considered to be repetition of left_bound != -1, pattern if
3455 // children_.empty(), otherwise "SEQ" or "OR", defined by the pattern_
3456 // field.
3457 std::string
3458 pattern_; // Either pattern, or "SEQ" or "OR" (if !children_.empty()).
3459 std::vector<regex_node> children_; // Children, when SEQ or OR.
3460 int left_bound_, right_bound_; // Left and right bounds of the repetition,
3461 // or -1 if not a repetition.
3462 double
3463 log_space_num_ways_; // Log space number of ways to match the pattern.
3464 std::optional<distinct_container<char>>
3465 distinct_; // Distinct generator for the pattern, for [chars].
3466
3467 // c or [chars].
3468 regex_node(const std::string &pattern)
3469 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3470 if (pattern.size() == 1) {
3471 log_space_num_ways_ = math::detail::LOG_ONE;
3472 return;
3473 }
3474 tgen_ensure_against_bug(pattern[0] == '[' and pattern.back() == ']',
3475 "str: invalid regex: expected character class");
3476 int size = static_cast<int>(pattern.size()) - 2;
3477 log_space_num_ways_ =
3478 static_cast<double>(math::detail::log_space(size));
3479 distinct_ = distinct_container<char>(pattern.substr(1, size));
3480 }
3481 // SEQ or OR.
3482 regex_node(const std::string &pattern, std::vector<regex_node> &children)
3483 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3484 if (pattern == "SEQ") {
3485 // Multiply the number of ways.
3486 log_space_num_ways_ = math::detail::LOG_ONE;
3487 for (const auto &child : children)
3488 log_space_num_ways_ += child.log_space_num_ways_;
3489 } else if (pattern == "OR") {
3490 // Add the number of ways.
3491 log_space_num_ways_ = math::detail::LOG_ZERO;
3492 for (const auto &child : children)
3493 log_space_num_ways_ =
3494 static_cast<double>(math::detail::add_log_space(
3495 log_space_num_ways_, child.log_space_num_ways_));
3496 } else
3497 tgen_ensure_against_bug("str: invalid regex: expected SEQ or OR");
3498
3499 children_ = std::move(children);
3500 children.clear();
3501 }
3502 // REP.
3503 regex_node(int left_bound, int right_bound, regex_node &child)
3504 : pattern_("REP"), left_bound_(left_bound), right_bound_(right_bound) {
3505 log_space_num_ways_ = math::detail::LOG_ZERO;
3506 for (int i = left_bound; i <= right_bound; ++i)
3507 log_space_num_ways_ =
3508 static_cast<double>(math::detail::add_log_space(
3509 log_space_num_ways_, i * child.log_space_num_ways_));
3510
3511 children_.push_back(std::move(child));
3512 }
3513};
3514
3515// State of the regex parser.
3516struct regex_state {
3517 std::vector<regex_node> cur; // Current sequence of nodes.
3518 std::vector<regex_node> branches; // Branches of the current OR group.
3519};
3520
3521// Creates a SEQ node from the current state.
3522inline regex_node make_regex_seq(regex_state &st) {
3523 return regex_node("SEQ", st.cur);
3524}
3525
3526// Finishes current state.
3527inline regex_node finish_regex_state(regex_state &st) {
3528 // SEQ.
3529 if (st.branches.empty())
3530 return make_regex_seq(st);
3531
3532 // OR.
3533 st.branches.push_back(make_regex_seq(st));
3534 return regex_node("OR", st.branches);
3535}
3536
3537// Parses a regex pattern into a tree, computing the number of ways to match the
3538// pattern.
3539inline regex_node parse_regex(std::string regex) {
3540 std::string new_regex;
3541 for (char c : regex)
3542 if (c != ' ')
3543 new_regex += c;
3544 swap(regex, new_regex);
3545 regex_state cur;
3546 std::vector<regex_state> stack;
3547
3548 for (size_t i = 0; i < regex.size(); ++i) {
3549 char c = regex[i];
3550
3551 if (c == '(') {
3552 // Pushes the current state to the stack.
3553 stack.push_back(std::move(cur));
3554 cur = regex_state();
3555 } else if (c == ')') {
3556 // Finishes the current state, and adds it to the parent.
3557 regex_node node = finish_regex_state(cur);
3558
3559 tgen_ensure(!stack.empty(), "str: invalid regex: unmatched `)`");
3560 cur = std::move(stack.back());
3561 stack.pop_back();
3562
3563 cur.cur.push_back(std::move(node));
3564 } else if (c == '|') {
3565 // Starts a new OR group.
3566 regex_node node = make_regex_seq(cur);
3567 cur.branches.push_back(std::move(node));
3568 } else if (c == '[') {
3569 // Parses a character class.
3570 std::string chars;
3571
3572 for (++i; i < regex.size() and regex[i] != ']'; ++i) {
3573 if (i + 2 < regex.size() and regex[i + 1] == '-') {
3574 char a = regex[i], b = regex[i + 2];
3575 if (a > b)
3576 std::swap(a, b);
3577 for (char x = a; x <= b; ++x)
3578 chars += x;
3579 i += 2;
3580 } else
3581 chars += regex[i];
3582 }
3583
3584 tgen_ensure(i < regex.size() and regex[i] == ']',
3585 "str: invalid regex: unmatched `[`");
3586 cur.cur.emplace_back("[" + chars + "]");
3587 } else if (c == '{') {
3588 // Parses a repetition.
3589 ++i;
3590 int l = -1, r = -1;
3591
3592 while (i < regex.size() and
3593 isdigit(static_cast<unsigned char>(regex[i]))) {
3594 if (l == -1)
3595 l = 0;
3596 tgen_ensure(l <= static_cast<int>(1e8),
3597 "str: invalid regex: number too large inside `{}`");
3598 l = 10 * l + (regex[i] - '0');
3599 ++i;
3600 }
3601
3602 if (i < regex.size() and regex[i] == ',') {
3603 ++i;
3604 while (i < regex.size() and
3605 isdigit(static_cast<unsigned char>(regex[i]))) {
3606 if (r == -1)
3607 r = 0;
3609 r <= static_cast<int>(1e8),
3610 "str: invalid regex: number too large inside `{}`");
3611 r = 10 * r + (regex[i] - '0');
3612 ++i;
3613 }
3614 } else
3615 r = l;
3616
3617 tgen_ensure(i < regex.size() and regex[i] == '}',
3618 "str: invalid regex: unmatched `{`");
3619 tgen_ensure(l != -1 and r != -1,
3620 "str: invalid regex: missing number inside `{}`");
3621 tgen_ensure(l <= r,
3622 "str: invalid regex: invalid range inside `{}`");
3623
3624 // Creates a REP node from the previous node.
3625 tgen_ensure(!cur.cur.empty(),
3626 "str: invalid regex: expected expression before `{}`");
3627
3628 regex_node rep(l, r, cur.cur.back());
3629 cur.cur.pop_back();
3630 cur.cur.push_back(std::move(rep));
3631 } else {
3632 // Creates a char node.
3633 cur.cur.emplace_back(std::string(1, c));
3634 }
3635 }
3636
3637 tgen_ensure(stack.empty(), "str: invalid regex: unmatched `(`");
3638 return finish_regex_state(cur);
3639}
3640
3641// Generates a uniformly random string that matches the given regex.
3642inline void gen_regex(const regex_node &node, std::string &str) {
3643 // For [chars], generate a random character from the list.
3644 if (node.pattern_[0] == '[') {
3645 str += node.pattern_[1 + next<int>(
3646 0, static_cast<int>(node.pattern_.size()) -
3647 3)];
3648 return;
3649 }
3650
3651 // For REP, generate a random number of times to repeat the pattern.
3652 if (node.left_bound_ != -1) {
3653 // Generates a random value W from 0 to num_ways.
3654 // log(W) = log(random(0, 1) * num_ways)
3655 // = log(random(0, 1)) + log(num_ways).
3656 double log_rand =
3657 static_cast<double>(math::detail::log_space(next<double>(0, 1))) +
3658 node.log_space_num_ways_;
3659 double cur_prob = math::detail::LOG_ZERO;
3660 double child_num_ways = node.children_[0].log_space_num_ways_;
3661
3662 for (int i = node.left_bound_; i <= node.right_bound_; ++i) {
3663 cur_prob = static_cast<double>(
3664 math::detail::add_log_space(cur_prob, i * child_num_ways));
3665 if (log_rand <= cur_prob) {
3666 for (int j = 0; j < i; ++j)
3667 gen_regex(node.children_[0], str);
3668 return;
3669 }
3670 }
3671
3672 tgen_ensure_against_bug(false,
3673 "str: log_rand > cur_prob in REP gen_regex");
3674 }
3675
3676 // For SEQ, generate all children.
3677 if (!node.children_.empty() and node.pattern_ == "SEQ") {
3678 for (const regex_node &child : node.children_)
3679 gen_regex(child, str);
3680 return;
3681 }
3682
3683 // For OR, generate a random child.
3684 if (!node.children_.empty() and node.pattern_ == "OR") {
3685 // Generates a random value W from 0 to num_ways.
3686 // log(W) = log(random(0, 1) * num_ways)
3687 // = log(random(0, 1)) + log(num_ways).
3688 double log_rand =
3689 static_cast<double>(math::detail::log_space(next<double>(0, 1))) +
3690 node.log_space_num_ways_;
3691 double cur_prob = math::detail::LOG_ZERO;
3692
3693 for (const regex_node &child : node.children_) {
3694 cur_prob = static_cast<double>(math::detail::add_log_space(
3695 cur_prob, child.log_space_num_ways_));
3696 if (log_rand <= cur_prob) {
3697 gen_regex(child, str);
3698 return;
3699 }
3700 }
3701
3702 tgen_ensure_against_bug(false,
3703 "str: log_rand > cur_prob in OR gen_regex");
3704 }
3705
3706 // For char, generate the character.
3707 detail::tgen_ensure_against_bug(
3708 node.pattern_.size() == 1,
3709 "str: invalid regex: expected single character, but got `" +
3710 node.pattern_ + "`");
3711 str += node.pattern_[0];
3712}
3713
3714// Formats a regex string with given arguments.
3715template <typename... Args>
3716std::string regex_format(const std::string &s, Args &&...args) {
3717 if constexpr (sizeof...(Args) == 0) {
3718 return s;
3719 } else {
3720 int size = std::snprintf(nullptr, 0, s.c_str(), args...) + 1;
3721 std::string buf(size, '\0');
3722 std::snprintf(buf.data(), size, s.c_str(), args...);
3723 buf.pop_back(); // remove '\0'
3724 return buf;
3725 }
3726}
3727
3728} // namespace detail
3729
3730/*
3731 * String generator.
3732 */
3733
3734struct str : gen_base<str> {
3735 std::optional<list<char>> list_; // List of characters.
3736 std::optional<detail::regex_node>
3737 root_; // Root node of the regex tree for the whole string.
3738
3739 // Creates generator for strings of size 'size', with random characters in
3740 // [value_left, value_right].
3741 str(int size, char value_left = 'a', char value_right = 'z') {
3742 tgen_ensure(size > 0, "str: size must be positive");
3743 list_ = list<char>(size, value_left, value_right);
3744 }
3745
3746 // Creates generator for strings of size 'size', with random characters in
3747 // 'chars'.
3748 str(int size, std::set<char> chars) {
3749 tgen_ensure(size > 0, "str: size must be positive");
3750 list_ = list<char>(size, chars);
3751 }
3752
3753 // Creates generator for strings that match the given regex.
3754 template <typename... Args> str(const std::string &regex, Args &&...args) {
3755 tgen_ensure(regex.size() > 0, "str: regex must be non-empty");
3756
3757 root_ = detail::parse_regex(
3758 detail::regex_format(regex, std::forward<Args>(args)...));
3759 }
3760
3761 // Restricts strings for str[idx] = value.
3762 str &fix(int idx, char character) {
3763 tgen_ensure(!root_, "str: cannot add restriction for regex");
3764 list_->fix(idx, character);
3765 return *this;
3766 }
3767
3768 // Restricts strings for list[S] to be equal, for given subset S of indices.
3769 str &equal(std::set<int> indices) {
3770 tgen_ensure(!root_, "str: cannot add restriction for regex");
3771 list_->equal(indices);
3772 return *this;
3773 }
3774
3775 // Restricts strings for str[idx_1] = str[idx_2].
3776 str &equal(int idx_1, int idx_2) {
3777 tgen_ensure(!root_, "str: cannot add restriction for regex");
3778 list_->equal(idx_1, idx_2);
3779 return *this;
3780 }
3781
3782 // Restricts strings for str[left..right] to have all equal values.
3783 str &equal_range(int left, int right) {
3784 tgen_ensure(!root_, "str: cannot add restriction for regex");
3785 list_->equal_range(left, right);
3786 return *this;
3787 }
3788
3789 // Restricts strings for all equal chars.
3791 tgen_ensure(!root_, "str: cannot add restriction for regex");
3792 list_->all_equal();
3793 return *this;
3794 }
3795
3796 // Restricts strings for str[left..right] to be a palindrome.
3797 str &palindrome(int left, int right) {
3798 tgen_ensure(!root_, "str: cannot add restriction for regex");
3799 tgen_ensure(0 <= left and left <= right and right < list_->size_,
3800 "str: range indices must be valid");
3801 for (int i = left; i < right - (i - left); ++i)
3802 equal(i, right - (i - left));
3803 return *this;
3804 }
3805
3806 // Restricts strings for the entire string to be a palindrome.
3808 tgen_ensure(!root_, "str: cannot add restriction for regex");
3809 return palindrome(0, list_->size_ - 1);
3810 }
3811
3812 // Restricts strings for str[S] to be different (distinct), for given subset
3813 // S of indices.
3814 str &different(std::set<int> indices) {
3815 tgen_ensure(!root_, "str: cannot add restriction for regex");
3816 list_->different(indices);
3817 return *this;
3818 }
3819
3820 // Restricts strings for str[idx_1] != str[idx_2].
3821 str &different(int idx_1, int idx_2) {
3822 tgen_ensure(!root_, "str: cannot add restriction for regex");
3823 list_->different(idx_1, idx_2);
3824 return *this;
3825 }
3826
3827 // Restricts lists for list[left..right] to have all different chars.
3828 str &different_range(int left, int right) {
3829 tgen_ensure(!root_, "str: cannot add restriction for regex");
3830 list_->different_range(left, right);
3831 return *this;
3832 }
3833
3834 // Restricts strings for all chars to be different.
3836 tgen_ensure(!root_, "str: cannot add restriction for regex");
3837 list_->all_different();
3838 return *this;
3839 }
3840
3841 // Restricts adjacent characters to be different: str[i] != str[i+1].
3843 tgen_ensure(!root_, "str: cannot add restriction for regex");
3844 list_->adjacent_different();
3845 return *this;
3846 }
3847
3848 // str value.
3850 using tgen_is_sequential_tag = detail::is_sequential_tag;
3851
3852 using value_type = char;
3853 using std_type = std::string;
3854 std::string str_;
3855
3856 value(const std::string &str) : str_(str) {
3857 tgen_ensure(!str_.empty(), "str: value: cannot be empty");
3858 }
3859
3860 // Fetches size.
3861 int size() const { return static_cast<int>(str_.size()); }
3862
3863 // Fetches position idx.
3864 char &operator[](int idx) {
3865 tgen_ensure(0 <= idx and idx < size(),
3866 "str: value: index out of bounds");
3867 return str_[idx];
3868 }
3869 const char &operator[](int idx) const {
3870 tgen_ensure(0 <= idx and idx < size(),
3871 "str: value: index out of bounds");
3872 return str_[idx];
3873 }
3874
3875 // Sorts characters in non-decreasing order.
3876 // O(n log n).
3878 std::sort(str_.begin(), str_.end());
3879 return *this;
3880 }
3881
3882 // Reverses string.
3883 // O(n).
3885 std::reverse(str_.begin(), str_.end());
3886 return *this;
3887 }
3888
3889 // Lowercases all characters.
3890 // O(n).
3892 for (char &c : str_)
3893 c = static_cast<char>(
3894 std::tolower(static_cast<unsigned char>(c)));
3895 return *this;
3896 }
3897
3898 // Uppercases all characters.
3899 // O(n).
3901 for (char &c : str_)
3902 c = static_cast<char>(
3903 std::toupper(static_cast<unsigned char>(c)));
3904 return *this;
3905 }
3906
3907 // Concatenates two values.
3908 // Linear.
3909 value operator+(const value &rhs) const {
3910 return value(str_ + rhs.str_);
3911 }
3912
3913 // Shuffles string uniformly.
3914 // O(n).
3916 for (int i = 0; i < size(); ++i)
3917 std::swap(str_[i], str_[next(0, size() - 1)]);
3918 return *this;
3919 }
3920
3921 // Returns a random character uniformly.
3922 // O(1).
3923 char pick() const { return str_[next<int>(0, size() - 1)]; }
3924
3925 // Returns str_[i] with probability proportional to distribution[i].
3926 // O(1).
3927 template <typename Dist>
3928 char pick_by_distribution(const std::vector<Dist> &distribution) const {
3929 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
3930 "value and distribution must have the same size");
3931 return str_[next_by_distribution(distribution)];
3932 }
3933 template <typename Dist>
3934 char pick_by_distribution(
3935 const std::initializer_list<Dist> &distribution) const {
3936 return pick_by_distribution(std::vector<Dist>(distribution));
3937 }
3938
3939 // Chooses k characters uniformly, as in a subsequence of size k.
3940 // O(n).
3941 value choose(int k) const {
3942 tgen_ensure(0 < k and k <= size(),
3943 "number of elements to choose must be valid");
3944 std::string new_str;
3945 int need = k;
3946 for (int i = 0; need > 0; ++i) {
3947 int left = size() - i;
3948 if (next(1, left) <= need) {
3949 new_str.push_back(str_[i]);
3950 need--;
3951 }
3952 }
3953 return value(new_str);
3954 }
3955
3956 // Prints to std::ostream.
3957 friend std::ostream &operator<<(std::ostream &out, const value &val) {
3958 return out << val.str_;
3959 }
3960
3961 // Gets a std::string representing the value.
3962 std::string to_std() const { return std_type(str_); }
3963 };
3964
3965 // Generates str value.
3966 // If created from restrictions: O(n log n).
3967 // If created from regex: expected linear.
3968 value gen() const {
3969 if (root_) {
3970 // Regex.
3971 std::string ret_str;
3972 gen_regex(*root_, ret_str);
3973 return value(ret_str);
3974 } else {
3975 // List.
3976 std::vector<char> vec = list_->gen().to_std();
3977 return value(std::string(vec.begin(), vec.end()));
3978 }
3979 }
3980};
3981
3982/************
3983 * *
3984 * PAIR *
3985 * *
3986 ************/
3987
3988namespace detail {
3989
3990// Generates pair first == second.
3991// O(1).
3992template <typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3993 T L = std::max(L1, L2);
3994 T R = std::min(R1, R2);
3995
3996 tgen_ensure(L <= R, "pair: no valid values to generate");
3997 T x = next<T>(L, R);
3998 return {x, x};
3999}
4000
4001// Returns {R1-L1+1, R2-L2+1}.
4002template <typename T>
4003std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
4004 u128 n = static_cast<i128>(R1) - L1 + 1;
4005 u128 m = static_cast<i128>(R2) - L2 + 1;
4006 return {n, m};
4007}
4008
4009// Returns first + first+1 + ... + last,
4010// num_terms terms. Avoids overflow.
4011static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
4012 u128 x = first + last, y = num_terms;
4013
4014 // x * y / 2, avoiding overflow.
4015 if (x % 2 == 0)
4016 x /= 2;
4017 else
4018 y /= 2;
4019
4020 return x * y;
4021}
4022
4023// Generates pair first != second.
4024// O(1) expected.
4025template <typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
4026 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4027
4028 T L_intersect = std::max(L1, L2);
4029 T R_intersect = std::min(R1, R2);
4030 u128 inter = static_cast<i128>(R_intersect) - L_intersect + 1;
4031
4032 u128 total = n * m - inter;
4033 tgen_ensure(total > 0, "pair: no valid values to generate");
4034
4035 // Runs O(1) expected times in the worst case.
4036 T a, b;
4037 do {
4038 a = next<T>(L1, R1);
4039 b = next<T>(L2, R2);
4040 } while (a == b);
4041
4042 return {a, b};
4043}
4044
4045// For lt, splits 'second' into two regions:
4046// 1) second <= R1 -> number of 'first' is (second - L1)
4047// 2) second > R1 -> number of 'first' is (R1 - L1 + 1)
4048// Returns {count_region1, count_region2}.
4049// O(1).
4050template <typename T>
4051std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4052 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4053
4054 // 'second' must be >= L1 + 1.
4055 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4056 i128 R_second = R2;
4057
4058 // Split point for 'second'.
4059 i128 split = std::min<i128>(R_second, R1);
4060
4061 // Region 1: b in [L_second, split].
4062 u128 len1 = std::max<i128>(0, split - L_second + 1);
4063
4064 u128 count_region1 = 0;
4065 if (len1 > 0) {
4066 // For b in [L_second, split], there are (b - L1) ways.
4067 i128 first = L_second - L1;
4068 i128 last = split - L1;
4069
4070 // Arithmetic series first + (first + 1) + ... + last, len1 terms.
4071 count_region1 = pos_arith_sum(first, last, len1);
4072 }
4073
4074 // Region 2: b > R1.
4075 // For b in [R1+1, R_second], there are 'n' ways.
4076 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4077
4078 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4079 u128 count_region2 = len2 * n;
4080
4081 return {count_region1, count_region2};
4082}
4083
4084// Generates pair first < second.
4085// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4086template <typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4087 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4088
4089 // 'second' needs to be at least L1 + 1 to have a valid value for
4090 // 'first'.
4091 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4092 i128 R_second = R2;
4093
4094 // Splits 'second' into two regions:
4095 // 1) b <= R1 -> number of 'first' is (b - L1);
4096 // 2) b > R1 -> number of 'first' is (R1 - L1 + 1).
4097 i128 split = std::min<i128>(R_second, R1);
4098
4099 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4100 u128 total = count_region1 + count_region2;
4101 tgen_ensure(total > 0, "pair: no valid values to generate");
4102
4103 u128 k = detail::next128(total);
4104 if (k < count_region1) {
4105 // Region 1: invert arithmetic series.
4106
4107 // For b in [L_second, split].
4108 u128 len1 = std::max<i128>(0, split - L_second + 1);
4109
4110 // We consider b in [L_second, L_second + d].
4111 // Each b contributes (b - L1) = base + (b - L_second).
4112 // So we sum: base + (base+1) + ... + (base+d)
4113 // d in [0, len1).
4114
4115 i128 base = L_second - L1;
4116 i128 lo = 0, hi = static_cast<i128>(len1) - 1;
4117
4118 while (lo < hi) {
4119 i128 mid = lo + (hi - lo) / 2;
4120
4121 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4122 lo = mid + 1;
4123 else
4124 hi = mid;
4125 }
4126 i128 d = lo;
4127
4128 // Subtracts prefix sum with d-1 terms from k.
4129 if (d > 0)
4130 k -= pos_arith_sum(base, base + d - 1, d);
4131
4132 return {L1 + static_cast<T>(k), L_second + d};
4133 } else {
4134 // Region 2: uniform block of size n.
4135 k -= count_region1;
4136
4137 // For b in [R1+1, R_second], there are 'n' ways.
4138 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4139
4140 return {L1 + static_cast<T>(k % n),
4141 L_second_region2 + static_cast<T>(k / n)};
4142 }
4143}
4144
4145// Generates pair first > second.
4146// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4147template <typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4148 auto [first, second] = gen_lt(L2, R2, L1, R1);
4149 return {second, first};
4150}
4151
4152// Generates pair first <= second.
4153// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4154template <typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4155 // Counts how many pairs are there with first = second.
4156 i128 L_intersect = std::max(L1, L2);
4157 i128 R_intersect = std::min(R1, R2);
4158 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4159
4160 // Counts how many pairs are there with first < second.
4161 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4162 u128 lt_count = lt_region1 + lt_region2;
4163
4164 u128 total = eq_count + lt_count;
4165 tgen_ensure(total > 0, "pair: no valid values to generate");
4166
4167 if (detail::next128(total) < eq_count)
4168 return gen_eq(L1, R1, L2, R2);
4169 return gen_lt(L1, R1, L2, R2);
4170}
4171
4172// Generates pair first >= second.
4173// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4174template <typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4175 auto [first, second] = gen_leq(L2, R2, L1, R1);
4176 return {second, first};
4177}
4178
4179}; // namespace detail
4180
4181/*
4182 * Pair generator.
4183 *
4184 * Pairs of integral types.
4185 */
4186
4187template <typename T> struct pair : gen_base<pair<T>> {
4188 std::pair<T, T> first_, second_; // Range of first and second values.
4189 // Type of restriction.
4190 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4191 restriction_type type_ = restriction_type::unspecified;
4192
4193 // Creates a pair with random values in [first_l, first_r] and [second_l,
4194 // second_r].
4195 pair(T first_left, T first_right, T second_left, T second_right)
4196 : first_(first_left, first_right), second_(second_left, second_right) {
4197 tgen_ensure(first_left <= first_right,
4198 "pair: first range must be valid");
4199 tgen_ensure(second_left <= second_right,
4200 "pair: second range must be valid");
4201 }
4202
4203 // Creates a pair with random values in [both_l, both_r].
4204 pair(T both_left, T both_right)
4205 : pair(both_left, both_right, both_left, both_right) {}
4206
4207 // Restricts pair for first = second.
4209 type_ = restriction_type::eq;
4210 return *this;
4211 }
4212
4213 // Restricts pair for first != second.
4215 type_ = restriction_type::neq;
4216 return *this;
4217 }
4218
4219 // Restricts pair for first < second.
4221 type_ = restriction_type::lt;
4222 return *this;
4223 }
4224
4225 // Restricts pair for first > second.
4227 type_ = restriction_type::gt;
4228 return *this;
4229 }
4230
4231 // Restricts pair for first <= second.
4233 type_ = restriction_type::leq;
4234 return *this;
4235 }
4236
4237 // Restricts pair for first >= second.
4239 type_ = restriction_type::geq;
4240 return *this;
4241 }
4242
4243 // Pair value.
4245 using value_type = T;
4246 using std_type = std::pair<T, T>;
4247
4248 std::pair<T, T> pair_;
4249 char sep_;
4250
4251 value(const std::pair<T, T> &pair) : pair_(pair), sep_(' ') {}
4252 value(const T &first, const T &second)
4253 : pair_(first, second), sep_(' ') {}
4254
4255 T first() const { return pair_.first; }
4256 T second() const { return pair_.second; }
4257
4258 // Sets the separator for the pair, for printing.
4259 value &separator(char sep) {
4260 sep_ = sep;
4261 return *this;
4262 }
4263
4264 // Prints to std::ostream, separated by sep_.
4265 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4266 return out << val.pair_.first << val.sep_ << val.pair_.second;
4267 }
4268
4269 // Gets a std::pair representing the value.
4270 auto to_std() const {
4271 if constexpr (!detail::is_generator_value<T>::value) {
4272 return pair_;
4273 } else {
4274 std::pair<typename T::std_type, typename T::std_type> pair(
4275 pair_.first.to_std(), pair_.second.to_std());
4276 return pair;
4277 }
4278 }
4279 };
4280
4281 // Generates a random pair.
4282 // O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4283 value gen() const {
4284 T L1 = first_.first, R1 = first_.second;
4285 T L2 = second_.first, R2 = second_.second;
4286
4287 switch (type_) {
4288 case restriction_type::unspecified:
4289 return {next<T>(L1, R1), next<T>(L2, R2)};
4290 case restriction_type::eq:
4291 return detail::gen_eq<T>(L1, R1, L2, R2);
4292 case restriction_type::neq:
4293 return detail::gen_neq<T>(L1, R1, L2, R2);
4294 case restriction_type::lt:
4295 return detail::gen_lt<T>(L1, R1, L2, R2);
4296 case restriction_type::gt:
4297 return detail::gen_gt<T>(L1, R1, L2, R2);
4298 case restriction_type::leq:
4299 return detail::gen_leq<T>(L1, R1, L2, R2);
4300 case restriction_type::geq:
4301 return detail::gen_geq<T>(L1, R1, L2, R2);
4302 }
4303 throw detail::error("pair: unknown restriction type");
4304 }
4305};
4306
4307/************
4308 * *
4309 * TREE *
4310 * *
4311 ************/
4312
4313namespace detail {
4314
4315// Generates edges from Prufer sequence.
4316// O(n).
4317inline std::vector<std::pair<int, int>> edges_from_prufer(std::vector<int> p) {
4318 int n = static_cast<int>(p.size()) + 2;
4319
4320 // Degrees.
4321 std::vector<int> d(n, 1);
4322 for (int i : p)
4323 d[i]++;
4324
4325 // Adds last vertex.
4326 p.push_back(n - 1);
4327
4328 // Finds first vertex with degree 1.
4329 int idx, u;
4330 idx = u = static_cast<int>(find(d.begin(), d.end(), 1) - d.begin());
4331
4332 // Generates edges.
4333 std::vector<std::pair<int, int>> edges;
4334 for (int v : p) {
4335 edges.emplace_back(u, v);
4336 if (--d[v] == 1 and v < idx)
4337 u = v;
4338 else
4339 idx = u = static_cast<int>(find(d.begin() + idx + 1, d.end(), 1) -
4340 d.begin());
4341 }
4342 return edges;
4343}
4344
4345// Disjoint set union (union-find) for connectivity queries.
4346struct dsu {
4347 std::vector<int> parent_;
4348 std::vector<unsigned char> rank_;
4349
4350 // Creates a dsu with `n` elements, indexed from 0 to n-1.
4351 // Initially every element is in its own set.
4352 // O(n).
4353 dsu(int n) : parent_(n), rank_(n, 0) {
4354 for (int i = 0; i < n; ++i)
4355 parent_[i] = i;
4356 }
4357
4358 // Adds new elements to the dsu, each in their own new set.
4359 // O(k) amortized.
4360 void add_elements(int k) {
4361 for (int i = 0; i < k; ++i) {
4362 int new_id = static_cast<int>(parent_.size());
4363 parent_.push_back(new_id);
4364 rank_.push_back(0);
4365 }
4366 }
4367
4368 // Finds representative of set containing i.
4369 // O(alpha(n)) amortized, O(log n) worst case.
4370 int find(int i) {
4371 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4372 }
4373
4374 // Merges components of `a` and `b`. Returns if the sets were united, and
4375 // false if a and b were in the same set.
4376 // O(alpha(n)) amortized, O(log n) worst case.
4377 bool unite(int a, int b) {
4378 a = find(a);
4379 b = find(b);
4380 if (a == b)
4381 return false;
4382 if (rank_[a] > rank_[b])
4383 std::swap(a, b);
4384 parent_[a] = b;
4385 if (rank_[a] == rank_[b])
4386 ++rank_[b];
4387 return true;
4388 }
4389};
4390
4391} // namespace detail
4392
4393// Forward declaration of wgraph.
4394template <typename VWeight, typename EWeight> struct wgraph;
4395
4396/*
4397 * Tree generator.
4398 *
4399 * Unrooted trees with `n` vertices, indexed from 0 to n-1.
4400 * These are unrooted undirected labeled trees, that is, isomorphism is not
4401 * taken into account. VWeight is the type of vertex weights, and EWeight is
4402 * the type of edge weights. Generator does not generate weights. The weights
4403 * are to be set in the wtree::value.
4404 */
4405
4406template <typename VWeight, typename EWeight>
4407struct wtree : gen_base<wtree<VWeight, EWeight>> {
4408 int n_; // Number of vertices.
4409 std::set<std::pair<int, int>> edges_; // Edges that were set.
4410
4411 // Creates tree generator with `n` vertices.
4412 // O(1).
4413 wtree(int n) : n_(n) {
4414 tgen_ensure(n > 0, "wtree: number of vertices must be positive");
4415 }
4416
4417 // Adds edge between u and v (this edge must be generated).
4418 // O(log n).
4419 wtree &add_edge(int u, int v) {
4420 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
4421 "wtree: vertices must be indexed in [0, n)");
4422 tgen_ensure(u != v, "wtree: cannot add self loop to tree");
4423
4424 if (u > v)
4425 std::swap(u, v);
4426 edges_.emplace(u, v);
4427 return *this;
4428 }
4429
4430 // Tree value.
4431 //
4432 // Edges are stored in both directions in adjacency list, but only u < v in
4433 // edge list.
4435 using std_type = std::pair<int, std::vector<std::set<int>>>;
4436
4437 int n_; // Number of vertices.
4438 std::vector<std::set<int>> adj_; // Adjacency list.
4439 std::vector<std::pair<int, int>> edges_; // Edge list.
4440 bool print_1_based_; // If should print vertex ids 1-based (print only).
4441 bool print_n_; // If should print n.
4442 std::optional<int> print_parents_; // If should print in parent style
4443 // (stores the root).
4444 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
4445 std::optional<std::vector<EWeight>>
4446 edge_weights_; // Edge weights (in same order as edges_).
4447 detail::dsu dsu_; // Connectivity of current edges (for cycle checks).
4448
4449 // Creates value from adjacency list.
4450 // O(n).
4451 value(const std::vector<std::set<int>> &adj)
4452 : n_(static_cast<int>(adj.size())), adj_(adj),
4453 print_1_based_(false), print_n_(false), dsu_(n_) {
4454 for (int u = 0; u < n_; ++u)
4455 for (auto v : adj[u]) {
4457 0 <= v and v < n_,
4458 "wtree: value: vertices must be indexed in [0, n)");
4459 // Symmetric adjacency: count each undirected edge once.
4460 if (u < v) {
4461 edges_.emplace_back(u, v);
4463 dsu_.unite(u, v),
4464 "wtree: value: initial graph must form a tree");
4465 }
4466 }
4467 }
4468
4469 // Creates value from `n` and edge list.
4470 // O(n).
4471 value(int n, const std::vector<std::pair<int, int>> &edges)
4472 : n_(n), adj_(n), print_1_based_(false), print_n_(false), dsu_(n) {
4473 edges_.reserve(edges.size());
4474 for (auto [u, v] : edges) {
4475 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n,
4476 "wtree: value: vertices must be indexed in [0, n)");
4477 tgen_ensure(dsu_.unite(u, v),
4478 "wtree: value: initial graph must form a tree");
4479 if (u > v)
4480 std::swap(u, v);
4481 edges_.emplace_back(u, v);
4482 adj_[u].insert(v);
4483 adj_[v].insert(u);
4484 }
4485 }
4486 value(int n, const std::set<std::pair<int, int>> &edges)
4487 : value(n, std::vector<std::pair<int, int>>(edges.begin(),
4488 edges.end())) {}
4489 value(int n, const std::initializer_list<std::pair<int, int>> &edges)
4490 : value(n, std::vector<std::pair<int, int>>(edges)) {}
4491
4492 // Creates tree from graph via Kruskal-like random spanning tree.
4493 // Implemented after wgraph definition.
4494 // O(n + m alpha(n)).
4495 value(const typename wgraph<VWeight, EWeight>::value &g);
4496
4497 // Weight type conversion.
4498 // O(n).
4499 template <typename NewVWeight, typename NewEWeight>
4500 typename wtree<NewVWeight, NewEWeight>::value
4501 convert_weight_types() const {
4502 tgen_ensure(!vertex_weights_.has_value() and
4503 !edge_weights_.has_value(),
4504 "wtree: value: cannot convert weight type after "
4505 "assigning weights");
4506
4507 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4508 new_tree.print_1_based_ = print_1_based_;
4509 new_tree.print_n_ = print_n_;
4510 new_tree.print_parents_ = print_parents_;
4511 return new_tree;
4512 }
4513
4514 // Fetches number of vertices.
4515 int n() const { return n_; }
4516
4517 // Fetches a const ref. to adjacency list.
4518 const std::vector<std::set<int>> &adj() const { return adj_; }
4519
4520 // Fetches a const ref. to edge list.
4521 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
4522
4523 // Fetches a const ref. to vertex weights.
4525 return vertex_weights_;
4526 }
4527
4528 // Fetches a const ref. to edge weights.
4530 return edge_weights_;
4531 }
4532
4533 // Sets vertex weights.
4534 // O(n).
4535 template <typename NewVWeight = VWeight>
4536 typename wtree<NewVWeight, EWeight>::value set_vertex_weights(
4537 const std::vector<NewVWeight> &vertex_weights) const {
4538 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
4539 "wtree: value: must give `n` vertex weights");
4540
4541 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4542 new_tree.vertex_weights_ = vertex_weights;
4543 return new_tree;
4544 }
4545
4546 // Sets edge weights.
4547 // O(n).
4548 template <typename NewEWeight = EWeight>
4549 typename wtree<VWeight, NewEWeight>::value
4550 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
4552 edge_weights.size() == edges().size(),
4553 "wtree: value: must give `edges().size()` edge weights");
4554
4555 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4556 new_tree.edge_weights_ = edge_weights;
4557 return new_tree;
4558 }
4559
4560 // Enables edge-weighted mode before adding weighted edges
4561 // incrementally. The tree must have no edges yet. O(1).
4563 tgen_ensure(edges().size() == 0,
4564 "wtree: value: edge_weighted requires a tree with no "
4565 "edges");
4566 tgen_ensure(!edge_weights_.has_value(),
4567 "wtree: value: tree is already edge-weighted");
4568
4569 edge_weights_ = std::vector<EWeight>();
4570 return *this;
4571 }
4572
4573 // Sets that should print vertex ids 1-based. Does not change stored
4574 // ids; use to_std_1_based() for a 1-based export.
4575 // O(1).
4577 print_1_based_ = true;
4578 return *this;
4579 }
4580
4581 // Prints `n` on a new line before printing the tree.
4582 // O(1).
4584 print_n_ = true;
4585 return *this;
4586 }
4587
4588 // Prints the tree in parent style.
4589 // If root = -1, the root is considered to be 0, and its parent is not
4590 // printed. Otherwise, prints the parent of the root as -1. If root = n,
4591 // randomizes the root. O(1).
4592 value &print_parents(int root = -1) {
4593 tgen_ensure(root == -1 or (0 <= root and root < n()) or root == n(),
4594 "wtree: value: root must be -1, `n`, or in [0, n)");
4595 print_parents_ = root;
4596 return *this;
4597 }
4598
4599 // Shuffles the tree's vertex labels (except those in `indices`,
4600 // which keep their current label) and edge order. The change is
4601 // applied eagerly to the underlying adjacency list, edge list,
4602 // vertex weights and edge weights.
4603 // O(n).
4604 value &shuffle_except(std::set<int> indices) {
4605 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
4606 // its new id. Vertices in `indices` keep their label; the others
4607 // are permuted among themselves.
4608 std::vector<int> new_label(n());
4609 std::vector<int> shuffled;
4610 for (int i = 0; i < n(); ++i) {
4611 if (indices.count(i))
4612 new_label[i] = i;
4613 else
4614 shuffled.push_back(i);
4615 }
4616 std::vector<int> targets = shuffled;
4617 tgen::shuffle(targets.begin(), targets.end());
4618 for (size_t k = 0; k < shuffled.size(); ++k)
4619 new_label[shuffled[k]] = targets[k];
4620
4621 // Rewrites adjacency list with new labels.
4622 std::vector<std::set<int>> new_adj(n());
4623 for (int u = 0; u < n(); ++u)
4624 for (int v : adj_[u])
4625 new_adj[new_label[u]].insert(new_label[v]);
4626 adj_ = std::move(new_adj);
4627
4628 // Rewrites edges with new labels (canonical undirected order).
4629 for (auto &[u, v] : edges_) {
4630 u = new_label[u];
4631 v = new_label[v];
4632 if (u > v)
4633 std::swap(u, v);
4634 }
4635
4636 // Permutes vertex weights to match the new labels.
4637 if (vertex_weights_.has_value()) {
4638 std::vector<VWeight> new_vw(n());
4639 for (int i = 0; i < n(); ++i)
4640 new_vw[new_label[i]] = (*vertex_weights_)[i];
4641 vertex_weights_ = std::move(new_vw);
4642 }
4643
4644 // Rebuilds the dsu so future `add_edge` calls see the new labels.
4645 dsu_ = detail::dsu(n());
4646 for (auto [u, v] : edges_)
4647 dsu_.unite(u, v);
4648
4649 // Shuffles edge order, keeping edge weights aligned.
4650
4651 std::vector<int> perm(edges_.size());
4652 std::iota(perm.begin(), perm.end(), 0);
4653 tgen::shuffle(perm.begin(), perm.end());
4654
4655 std::vector<std::pair<int, int>> new_edges;
4656 std::optional<std::vector<EWeight>> new_ew;
4657 if (edge_weights_.has_value())
4658 new_ew = std::vector<EWeight>();
4659 for (int i : perm) {
4660 new_edges.push_back(edges_[i]);
4661 if (new_ew.has_value())
4662 new_ew->push_back((*edge_weights_)[i]);
4663 }
4664 edges_ = new_edges;
4665 if (new_ew.has_value())
4666 edge_weights_ = new_ew;
4667
4668 return *this;
4669 }
4670
4671 // Shuffles the tree's vertices and edge order.
4672 // O(n).
4673 value &shuffle() { return shuffle_except({}); }
4674
4675 // Adds edge (u, v).
4676 // O(log n) amortized.
4677 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
4678 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
4679 "wtree: value: vertex ids must be valid");
4680
4681 if (u > v)
4682 std::swap(u, v);
4683
4684 if (adj_[u].count(v))
4685 return *this;
4686
4687 adj_[u].insert(v);
4688 adj_[v].insert(u);
4689 edges_.emplace_back(u, v);
4690 tgen_ensure(dsu_.unite(u, v),
4691 "wtree: value: added edge must not create a cycle");
4692
4693 if (w.has_value()) {
4694 tgen_ensure(edge_weights().has_value(),
4695 "wtree: value: cannot add weighted edge to "
4696 "edge-unweighted tree");
4697
4698 edge_weights_->push_back(*w);
4699 } else
4700 tgen_ensure(!edge_weights().has_value(),
4701 "wtree: value: cannot add unweighted edge to "
4702 "edge-weighted tree");
4703
4704 return *this;
4705 }
4706
4707 // Links tree with another `rhs`, adding the edge between u (in left
4708 // tree) and v (in right tree). Ids for added vertices are updated
4709 // accordingly.
4710 // O(rhs.n + rhs.m * log n) amortized.
4711 value &link(const value &rhs, int new_u, int new_v,
4712 std::optional<EWeight> new_w = std::nullopt) {
4713 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
4714 new_v < rhs.n(),
4715 "wtree: value: vertex ids must be valid");
4716
4717 // Edges from right-hand side.
4718 int shift = n();
4719 add_vertices(rhs.n(), rhs.vertex_weights());
4720 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4721 auto [u, v] = rhs.edges()[i];
4722 add_edge(shift + u, shift + v,
4723 rhs.edge_weights().has_value()
4724 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4725 : std::nullopt);
4726 }
4727
4728 // New edge.
4729 add_edge(new_u, shift + new_v, new_w);
4730
4731 return *this;
4732 }
4733
4734 // Glues the tree with another `rhs` such that index_pairs[i].first is
4735 // considered to be the same as index_pairs[i].second. Ids for added
4736 // vertices are updated accordingly.
4737 // O(rhs.n + rhs.m * log n) amortized.
4738 value &glue(const value &rhs,
4739 std::set<std::pair<int, int>> index_pairs) {
4740 // Checks validity of indices.
4741 std::set<int> idx_left, idx_right;
4742 std::vector<int> right_id_to_left(rhs.n(), -1);
4743 for (auto [l, r] : index_pairs) {
4745 0 <= l and l < n() and 0 <= r and r < rhs.n(),
4746 "wtree: value: vertex indices to glue must be valid");
4747 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
4748 "wtree: value: must not have repeated indices "
4749 "on the same side to glue");
4750
4751 idx_left.insert(l);
4752 idx_right.insert(r);
4753 right_id_to_left[r] = l;
4754 }
4755
4756 // Computes new ids of right vertices.
4757 std::vector<int> new_right_id(rhs.n(), -1);
4758 int intersection_lt = 0;
4759 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4760 for (int i = 0; i < rhs.n(); ++i) {
4761 if (right_id_to_left[i] != -1) {
4762 // Is in intersection.
4763 ++intersection_lt;
4764 new_right_id[i] = right_id_to_left[i];
4765 } else {
4766 // New id.
4767 new_right_id[i] = n() + i - intersection_lt;
4768 if (rhs.vertex_weights().has_value()) {
4769 if (!rhs_vertex_weights.has_value())
4770 rhs_vertex_weights = std::vector<VWeight>();
4771 rhs_vertex_weights->push_back(
4772 (*rhs.vertex_weights())[i]);
4773 }
4774 }
4775 }
4776
4777 // Adds new vertices and edges.
4778 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4779 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
4780 auto [u, v] = rhs.edges()[i];
4781 add_edge(new_right_id[u], new_right_id[v],
4782 rhs.edge_weights().has_value()
4783 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4784 : std::nullopt);
4785 }
4786
4787 return *this;
4788 }
4789 value &glue(const value &rhs,
4790 std::initializer_list<std::pair<int, int>> il) {
4791 return glue(rhs, std::set<std::pair<int, int>>(il));
4792 }
4793
4794 // Glues the tree with another `rhs` at `indices`. That is, idx in
4795 // `indices` are considered to be the same vertex. Ids for added
4796 // vertices are updated accordingly.
4797 // O(rhs.n).
4798 value &glue(const value &rhs, std::set<int> indices) {
4799 std::set<std::pair<int, int>> index_pairs;
4800 for (auto i : indices)
4801 index_pairs.emplace(i, i);
4802 return glue(rhs, index_pairs);
4803 }
4804 value &glue(const value &rhs, const std::initializer_list<int> &il) {
4805 return glue(rhs, std::set<int>(il));
4806 }
4807
4808 // Prints to std::ostream.
4809 // O(n).
4810 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4811 if (val.print_n_)
4812 out << val.n() << '\n';
4813
4814 // Prints vertex weights.
4815 if (val.vertex_weights()) {
4816 for (int i = 0; i < val.n(); ++i) {
4817 if (i > 0)
4818 out << " ";
4819 out << (*val.vertex_weights())[i];
4820 }
4821 out << '\n';
4822 }
4823
4824 tgen_ensure(static_cast<int>(val.edges().size()) == val.n() - 1,
4825 "wtree: value: invalid tree to print (number of edges "
4826 "must be `n` - 1)");
4827
4828 // Prints in parent style.
4829 if (val.print_parents_.has_value()) {
4830 tgen_ensure(!val.edge_weights().has_value(),
4831 "wtree: value: cannot print parent style if edges "
4832 "are weighted");
4833
4834 int root = *val.print_parents_;
4835 bool skip_parent_0 = root == -1;
4836 if (root == -1)
4837 root = 0;
4838 if (root == val.n())
4839 root = next(0, val.n() - 1);
4840
4841 std::vector<int> parent(val.n(), -1);
4842
4843 std::queue<int> q;
4844 std::vector<int> vis(val.n(), false);
4845 q.push(root);
4846 vis[root] = true;
4847
4848 while (q.size()) {
4849 int u = q.front();
4850 q.pop();
4851 for (int v : val.adj()[u])
4852 if (!vis[v]) {
4853 vis[v] = true;
4854 q.push(v);
4855 parent[v] = u;
4856 }
4857 }
4858
4859 if (skip_parent_0) {
4860 for (int i = 1; i < val.n(); ++i) {
4862 parent[i] < i,
4863 "wtree: value: parent of i must be less than i for "
4864 "printing in parent style if root is -1");
4865
4866 if (i > 1)
4867 out << " ";
4868 out << parent[i] + val.print_1_based_;
4869 }
4870 } else {
4871 for (int i = 0; i < val.n(); ++i) {
4872 if (i > 0)
4873 out << " ";
4874 out << (parent[i] == -1 ? -1 : parent[i]) +
4875 val.print_1_based_;
4876 }
4877 }
4878
4879 out << '\n';
4880 return out;
4881 }
4882
4883 // Prints edges.
4884 for (int i = 0; i < static_cast<int>(val.edges().size()); ++i) {
4885 auto [u, v] = val.edges()[i];
4886 out << (u + val.print_1_based_) << " "
4887 << (v + val.print_1_based_);
4888
4889 // Edge weight.
4890 if (val.edge_weights().has_value())
4891 out << " " << (*val.edge_weights())[i];
4892
4893 out << '\n';
4894 }
4895
4896 return out;
4897 }
4898
4899 // Gets a std::pair<n, adj> representing the value (0-based).
4900 // Unaffected by print_1_based().
4901 std::pair<int, std::vector<std::set<int>>> to_std() const {
4902 return std_type(n_, adj_);
4903 }
4904
4905 // Gets a 1-based (n, adj): labels +1, adj size n+1, index 0 unused.
4906 // Unaffected by print_1_based().
4907 std::pair<int, std::vector<std::set<int>>> to_std_1_based() const {
4908 std::vector<std::set<int>> adj(n_ + 1);
4909 for (int u = 0; u < n_; ++u)
4910 for (int v : adj_[u])
4911 adj[u + 1].insert(v + 1);
4912 return std_type(n_, adj);
4913 }
4914
4915 private:
4916 // Adds `k` vertices to the tree (labeled n, n+1, ...n+k-1). Updates
4917 // `n` accordingly. This makes the tree invalid (not a tree anymore).
4918 // O(k) amortized.
4919 value &add_vertices(int k, std::optional<std::vector<VWeight>>
4920 new_vertex_weights = std::nullopt) {
4921 n_ += k;
4922 adj_.resize(n());
4923 if (new_vertex_weights.has_value()) {
4924 tgen_ensure(vertex_weights().has_value(),
4925 "wtree: value: cannot add weighted vertices to "
4926 "vertex-unweighted tree");
4928 static_cast<int>(new_vertex_weights->size()) == k,
4929 "wtree: value: number of vertex weights must be equal "
4930 "to number of added vertices");
4931
4932 vertex_weights_->insert(vertex_weights_->end(),
4933 new_vertex_weights->begin(),
4934 new_vertex_weights->end());
4935 } else
4936 tgen_ensure(!vertex_weights().has_value(),
4937 "wtree: value: cannot add unweighted vertices to "
4938 "vertex-weighted tree");
4939
4940 dsu_.add_elements(k);
4941
4942 return *this;
4943 }
4944 };
4945
4946 // Generates tree value.
4947 // O(n).
4948 value gen() const {
4949 // Constructs adjacency list.
4950 std::vector<std::vector<int>> adj(n_);
4951 for (auto [u, v] : edges_) {
4952 adj[u].push_back(v);
4953 adj[v].push_back(u);
4954 }
4955
4956 std::vector<int> comp_size;
4957 std::vector<std::vector<int>> component_ids;
4958 std::vector<bool> vis(n_, false);
4959 std::queue<int> q;
4960
4961 for (int i = 0; i < n_; ++i) {
4962 if (vis[i])
4963 continue;
4964
4965 vis[i] = true;
4966 q.push(i);
4967 comp_size.push_back(0);
4968 component_ids.emplace_back();
4969 while (q.size()) {
4970 int u = q.front();
4971 q.pop();
4972 ++comp_size.back();
4973 component_ids.back().push_back(u);
4974 for (int v : adj[u]) {
4975 if (!vis[v]) {
4976 vis[v] = true;
4977 q.push(v);
4978 }
4979 }
4980 }
4981 }
4982
4983 // Creates edges connecting the connected components by treating them as
4984 // vertices.
4985 std::vector<std::pair<int, int>> new_edges(edges_.begin(),
4986 edges_.end());
4987 if (comp_size.size() > 1) {
4988 std::vector<int> prufer_values = many_by_distribution(
4989 static_cast<int>(comp_size.size()) - 2, comp_size);
4990 for (auto [u, v] : detail::edges_from_prufer(prufer_values))
4991 new_edges.emplace_back(pick(component_ids[u]),
4992 pick(component_ids[v]));
4993 }
4994
4995 return value(n_, new_edges);
4996 }
4997
4998 // Generates a (not uniformly) random skewed tree.
4999 // Vertex 0 is the root. For each i in 1 .. n-1, parent(i) is
5000 // wnext(i, elongation), i.e. a value in [0, i) with skew controlled by
5001 // elongation (see wnext).
5002 // If elongation is small enough, generates a star (center 0).
5003 // If elongation is large enough, generates a path (endpoints 0 and n-1).
5004 // O(n).
5005 static value gen_skewed(int n, int elongation) {
5006 std::vector<std::pair<int, int>> edges;
5007 for (int i = 1; i < n; ++i)
5008 edges.emplace_back(i, wnext<int>(i, elongation));
5009 return value(n, edges);
5010 }
5011
5012 // Kruskal-like random tree: random vertex pairs until connected.
5013 // Not uniformly random.
5014 // O(n log(n) alpha(n)) expected.
5015 static value gen_kruskal(int n) {
5016 tgen_ensure(n > 0, "wtree: gen_kruskal: n must be positive");
5017 if (n == 1)
5018 return value(1, {});
5019
5020 detail::dsu components(n);
5021 std::vector<std::pair<int, int>> edges;
5022 edges.reserve(n - 1);
5023 while (edges.size() < size_t(n - 1)) {
5024 int u = next(0, n - 1);
5025 int v = next(0, n - 1);
5026 if (u == v)
5027 continue;
5028 if (components.unite(u, v))
5029 edges.emplace_back(u, v);
5030 }
5031 return value(n, edges);
5032 }
5033};
5034
5035/*
5036 * Other types of weighted-ness.
5037 */
5038
5039// Vertex weighted tree.
5040template <typename VWeight> using vtree = wtree<VWeight, int>;
5041
5042// Edge weighted tree.
5043template <typename EWeight> using etree = wtree<int, EWeight>;
5044
5045// Unweighted tree.
5046using tree = wtree<int, int>;
5047
5048/*************
5049 * *
5050 * GRAPH *
5051 * *
5052 *************/
5053
5054namespace detail {
5055
5056// Canonical undirected edge key for duplicate detection; stores (min(u, v),
5057// max(u, v)). O(1).
5058inline uint64_t undirected_edge_key(int u, int v) {
5059 if (u > v)
5060 std::swap(u, v);
5061 return (static_cast<uint64_t>(u) << 32) |
5062 static_cast<uint64_t>(static_cast<uint32_t>(v));
5063}
5064
5065// Directed edge key for duplicate detection; stores (u, v).
5066// O(1).
5067inline uint64_t directed_edge_key(int u, int v) {
5068 return (static_cast<uint64_t>(u) << 32) |
5069 static_cast<uint64_t>(static_cast<uint32_t>(v));
5070}
5071
5072// Maximum number of edges in a simple graph on n vertices.
5073// O(1).
5074inline long long max_graph_edges(int n, bool directed, bool self_loops) {
5075 if (n <= 0)
5076 return 0;
5077 if (directed)
5078 return self_loops ? static_cast<long long>(n) * n
5079 : static_cast<long long>(n) * (n - 1);
5080 return self_loops ? static_cast<long long>(n) * (n + 1) / 2
5081 : static_cast<long long>(n) * (n - 1) / 2;
5082}
5083
5084// Uniform random edge for rejection sampling.
5085// O(1) expected.
5086inline std::pair<int, int> get_random_graph_edge(int n, bool directed,
5087 bool self_loops) {
5088 if (directed) {
5089 if (self_loops)
5090 return {next<int>(0, n - 1), next<int>(0, n - 1)};
5091 int u = next<int>(0, n - 1);
5092 int v = next<int>(0, n - 1);
5093 while (u == v)
5094 v = next<int>(0, n - 1);
5095 return {u, v};
5096 }
5097 if (self_loops) {
5098 int u = next<int>(0, n - 1);
5099 int v = next<int>(0, n - 1);
5100 if (u > v)
5101 std::swap(u, v);
5102 return {u, v};
5103 }
5104 int u = next<int>(0, n - 1);
5105 int v = next<int>(0, n - 1);
5106 while (u == v)
5107 v = next<int>(0, n - 1);
5108 if (u > v)
5109 std::swap(u, v);
5110 return {u, v};
5111}
5112
5113// Decodes a linear edge index to (u, v) for an undirected simple graph,
5114// with u < v.
5115// O(log n).
5116inline std::pair<int, int> decode_undirected_simple_edge(int n, long long idx) {
5117 auto base = [&](int u) -> long long {
5118 return static_cast<long long>(u) * (n - 1) -
5119 static_cast<long long>(u) * (u - 1) / 2;
5120 };
5121 int lo = 0, hi = n - 2;
5122 while (lo < hi) {
5123 int mid = (lo + hi + 1) / 2;
5124 if (base(mid) <= idx)
5125 lo = mid;
5126 else
5127 hi = mid - 1;
5128 }
5129 return {lo, lo + 1 + int(idx - base(lo))};
5130}
5131
5132// Decodes a linear edge index to (u, v) for an undirected graph with loops,
5133// with u <= v.
5134// O(log n).
5135inline std::pair<int, int> decode_undirected_loops_edge(int n, long long idx) {
5136 auto base = [&](int u) -> long long {
5137 return static_cast<long long>(u) * n -
5138 static_cast<long long>(u) * (u - 1) / 2;
5139 };
5140 int lo = 0, hi = n - 1;
5141 while (lo < hi) {
5142 int mid = (lo + hi + 1) / 2;
5143 if (base(mid) <= idx)
5144 lo = mid;
5145 else
5146 hi = mid - 1;
5147 }
5148 return {lo, lo + int(idx - base(lo))};
5149}
5150
5151// Decodes a linear edge index to (u, v) for a directed simple graph (no loops).
5152// O(1).
5153inline std::pair<int, int> decode_directed_simple_edge(int n, long long idx) {
5154 int u = static_cast<int>(idx / (n - 1));
5155 int rem = static_cast<int>(idx % (n - 1));
5156 return {u, rem + (rem >= u)};
5157}
5158
5159// Decodes a linear edge index according to graph mode.
5160// O(log n) for undirected, O(1) for directed.
5161inline std::pair<int, int>
5162decode_graph_edge_index(int n, long long idx, bool directed, bool self_loops) {
5163 if (directed) {
5164 if (self_loops)
5165 return {int(idx / n), int(idx % n)};
5166 return decode_directed_simple_edge(n, idx);
5167 }
5168 if (self_loops)
5169 return decode_undirected_loops_edge(n, idx);
5170 return decode_undirected_simple_edge(n, idx);
5171}
5172
5173} // namespace detail
5174
5175/*
5176 * Graph generator.
5177 *
5178 * Graphs of `n` vertices labeled from 0 to n-1 and `m` edges.
5179 * These are labeled graphs, that is, isomorphism is not taken into
5180 * account. VWeight is the type of vertex weights, and EWeight is the type of
5181 * edge weights. Generator does not generate weights. The weights are to be set
5182 * in the wgraph::value.
5183 */
5184
5185template <typename VWeight, typename EWeight>
5186struct wgraph : gen_base<wgraph<VWeight, EWeight>> {
5187 int n_, m_; // Number of vertices and edges.
5188 std::set<std::pair<int, int>> edges_; // Edges that were set.
5189 bool is_directed_; // If graph is directed.
5190 bool has_self_loops_; // If self-loops are allowed.
5191
5192 // Creates graph generator with `n` vertices and `m` edges.
5193 // Additionally, you can set if the graph is directed and if self loops are
5194 // allowed.
5195 // O(1).
5196 wgraph(int n, int m, bool is_directed = false, bool has_self_loops = false)
5197 : n_(n), m_(m), is_directed_(is_directed),
5198 has_self_loops_(has_self_loops) {
5199 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
5200 }
5201
5202 // Adds edge between u and v (this edge must be generated).
5203 // O(log m).
5204 wgraph &add_edge(int u, int v) {
5205 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
5206 "wgraph: vertices must be indexed in [0, n)");
5207
5208 if (!is_directed_ and u > v)
5209 std::swap(u, v);
5210 edges_.emplace(u, v);
5211 tgen_ensure(static_cast<int>(edges_.size()) <= m_,
5212 "wgraph: too many edges were added");
5213 return *this;
5214 }
5215
5216 // Graph value.
5217 //
5218 // Edges are stored in both directions (if undirected) in adjacency list,
5219 // but only u < v in edge list.
5220 // Optimized for performance (lazy adjacency list; edge-list constructor
5221 // stores edges only).
5223 using std_type = std::tuple<int, int, std::vector<std::set<int>>>;
5224
5225 int n_; // Number of vertices.
5226 std::vector<std::set<int>> adj_; // Adjacency list.
5227 std::vector<std::pair<int, int>> edges_; // Edge list.
5228 bool is_directed_; // If graph is directed.
5229 bool print_1_based_; // If should print vertex ids 1-based (print only).
5230 bool print_nm_; // If should print n and m.
5231 mutable bool adj_built_{
5232 false}; // Lazy cache: true once adj_ is built from edges_; mutable
5233 // so const adj() can populate it.
5234 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
5235 std::optional<std::vector<EWeight>>
5236 edge_weights_; // Edge weights (in same order as edges_ ).
5237
5238 // Creates value from adjacency list. The edges
5239 // are considered to be directed.
5240 // O(n + m).
5241 value(const std::vector<std::set<int>> &adj, bool is_directed = false)
5242 : n_(static_cast<int>(adj.size())), adj_(adj),
5243 is_directed_(is_directed), print_1_based_(false),
5244 print_nm_(false), adj_built_(true) {
5245 for (int u = 0; u < n_; ++u)
5246 for (auto v : adj[u]) {
5248 0 <= v and v < n_,
5249 "wgraph: value: vertices must be indexed in [0, n)");
5250 // Undirected adjacency is symmetric: count each edge once
5251 // (canonical u <= v). Directed: every out-edge appears
5252 // once.
5253 if (is_directed_ or u <= v)
5254 edges_.emplace_back(u, v);
5255 }
5256 }
5257
5258 // Creates value from `n`, `m`, and edge list. The edges are
5259 // considered to be directed.
5260 // Optimized for performance (lazy adjacency list; unordered_set dedup).
5261 // O(m log m).
5262 value(int n, const std::vector<std::pair<int, int>> &edges = {},
5263 bool is_directed = false)
5264 : n_(n), edges_(), is_directed_(is_directed), print_1_based_(false),
5265 print_nm_(false), adj_built_(false) {
5266 edges_.reserve(edges.size());
5267 std::unordered_set<uint64_t> seen;
5268 seen.reserve(edges.size() * 2 + 1);
5269 for (auto [u, v] : edges) {
5271 0 <= std::min(u, v) and std::max(u, v) < n,
5272 "wgraph: value: vertices must be indexed in [0, n)");
5273 if (!is_directed_ and u > v)
5274 std::swap(u, v);
5275 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5276 : detail::undirected_edge_key(u, v);
5277 if (seen.insert(key).second)
5278 edges_.emplace_back(u, v);
5279 }
5280 }
5281 value(int n, const std::set<std::pair<int, int>> &edges,
5282 bool is_directed = false)
5283 : value(
5284 n,
5285 std::vector<std::pair<int, int>>(edges.begin(), edges.end()),
5286 is_directed) {}
5287 value(int n, const std::initializer_list<std::pair<int, int>> &edges,
5288 bool is_directed = false)
5289 : value(n, std::vector<std::pair<int, int>>(edges), is_directed) {}
5290
5291 // Creates graph from tree (undirected, same edges).
5292 // O(n).
5293 value(const typename wtree<VWeight, EWeight>::value &t)
5294 : value(t.n(), t.edges(), false) {
5295 if (t.vertex_weights().has_value()) {
5296 vertex_weights_ = *t.vertex_weights();
5297 }
5298 if (t.edge_weights().has_value()) {
5299 edge_weights_ = *t.edge_weights();
5300 }
5301 }
5302
5303 // Weight type conversion.
5304 // O(n + m).
5305 template <typename NewVWeight, typename NewEWeight>
5306 typename wgraph<NewVWeight, NewEWeight>::value
5307 convert_weight_types() const {
5308 tgen_ensure(!vertex_weights_.has_value() and
5309 !edge_weights_.has_value(),
5310 "wgraph: value: cannot convert weight type after "
5311 "assigning weights");
5312
5313 ensure_adj_built();
5314 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5315 adj_, is_directed_);
5316 new_graph.is_directed_ = is_directed_;
5317 new_graph.print_1_based_ = print_1_based_;
5318 new_graph.print_nm_ = print_nm_;
5319 return new_graph;
5320 }
5321
5322 // Fetches number of vertices.
5323 int n() const { return n_; }
5324
5325 // Fetches number of edges.
5326 int m() const { return static_cast<int>(edges_.size()); }
5327
5328 // Fetches if graph is directed;
5329 bool is_directed() const { return is_directed_; }
5330
5331 // Fetches a const ref. to adjacency list.
5332 const std::vector<std::set<int>> &adj() const {
5333 ensure_adj_built();
5334 return adj_;
5335 }
5336
5337 // Fetches a const ref. to edge set.
5338 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
5339
5340 // Fetches vertex weights.
5342 return vertex_weights_;
5343 }
5344
5345 // Fetches edge weights.
5347 return edge_weights_;
5348 }
5349
5350 // Sets vertex weights.
5351 // O(n + m).
5352 template <typename NewVWeight = VWeight>
5353 typename wgraph<NewVWeight, EWeight>::value set_vertex_weights(
5354 const std::vector<NewVWeight> &vertex_weights) const {
5355 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
5356 "wgraph: value: must give `n` vertex weights");
5357
5358 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5359 new_graph.vertex_weights_ = vertex_weights;
5360 return new_graph;
5361 }
5362
5363 // Sets edge weights.
5364 // O(n + m).
5365 template <typename NewEWeight = EWeight>
5366 typename wgraph<VWeight, NewEWeight>::value
5367 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
5368 tgen_ensure(static_cast<int>(edge_weights.size()) == m(),
5369 "wgraph: value: must give `m` edge weights");
5370
5371 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5372 new_graph.edge_weights_ = edge_weights;
5373 return new_graph;
5374 }
5375
5376 // Enables edge-weighted mode before adding weighted edges
5377 // incrementally. The graph must have no edges yet. O(1).
5379 tgen_ensure(m() == 0,
5380 "wgraph: value: edge_weighted requires a graph with no "
5381 "edges");
5382 tgen_ensure(!edge_weights_.has_value(),
5383 "wgraph: value: graph is already edge-weighted");
5384
5385 edge_weights_ = std::vector<EWeight>();
5386 return *this;
5387 }
5388
5389 // Sets that should print vertex ids 1-based. Does not change stored
5390 // ids; use to_std_1_based() for a 1-based export.
5391 // O(1).
5393 print_1_based_ = true;
5394 return *this;
5395 }
5396
5397 // Prints `n m` on a new line before printing the edges.
5398 // O(1).
5400 print_nm_ = true;
5401 return *this;
5402 }
5403
5404 // Shuffles the graph's vertex labels (except those in `indices`,
5405 // which keep their current label) and edge order. The change is
5406 // applied eagerly to the underlying adjacency list, edge list,
5407 // vertex weights and edge weights.
5408 // O(n + m).
5409 value &shuffle_except(std::set<int> indices) {
5410 ensure_adj_built();
5411 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
5412 // its new id. Vertices in `indices` keep their label; the others
5413 // are permuted among themselves.
5414 std::vector<int> new_label(n());
5415 std::vector<int> shuffled;
5416 for (int i = 0; i < n(); ++i) {
5417 if (indices.count(i))
5418 new_label[i] = i;
5419 else
5420 shuffled.push_back(i);
5421 }
5422 std::vector<int> targets = shuffled;
5423 tgen::shuffle(targets.begin(), targets.end());
5424 for (size_t k = 0; k < shuffled.size(); ++k)
5425 new_label[shuffled[k]] = targets[k];
5426
5427 // Rewrites adjacency list with new labels.
5428 std::vector<std::set<int>> new_adj(n());
5429 for (int u = 0; u < n(); ++u)
5430 for (int v : adj_[u])
5431 new_adj[new_label[u]].insert(new_label[v]);
5432 adj_ = new_adj;
5433
5434 // Rewrites edges with new labels (canonical undirected order).
5435 for (auto &[u, v] : edges_) {
5436 u = new_label[u];
5437 v = new_label[v];
5438 if (!is_directed_ and u > v)
5439 std::swap(u, v);
5440 }
5441
5442 // Permutes vertex weights to match the new labels.
5443 if (vertex_weights_.has_value()) {
5444 std::vector<VWeight> new_vw(n());
5445 for (int i = 0; i < n(); ++i)
5446 new_vw[new_label[i]] = (*vertex_weights_)[i];
5447 vertex_weights_ = new_vw;
5448 }
5449
5450 // Shuffles edge order, keeping edge weights aligned.
5451
5452 std::vector<int> perm(edges_.size());
5453 std::iota(perm.begin(), perm.end(), 0);
5454 tgen::shuffle(perm.begin(), perm.end());
5455
5456 std::vector<std::pair<int, int>> new_edges;
5457 std::optional<std::vector<EWeight>> new_ew;
5458 if (edge_weights_.has_value())
5459 new_ew = std::vector<EWeight>();
5460 for (int i : perm) {
5461 new_edges.push_back(edges_[i]);
5462 if (new_ew.has_value())
5463 new_ew->push_back((*edge_weights_)[i]);
5464 }
5465
5466 edges_ = new_edges;
5467 if (new_ew.has_value())
5468 edge_weights_ = new_ew;
5469
5470 return *this;
5471 }
5472
5473 // Shuffles the graph's vertices and edge order.
5474 // O(n + m).
5475 value &shuffle() { return shuffle_except({}); }
5476
5477 // Adds `k` vertices to the graph (labeled n, n+1, ...n+k-1). Updates
5478 // `n` accordingly.
5479 // O(k) amortized.
5480 value &add_vertices(int k, std::optional<std::vector<VWeight>>
5481 new_vertex_weights = std::nullopt) {
5482 ensure_adj_built();
5483 n_ += k;
5484 adj_.resize(n());
5485 if (new_vertex_weights.has_value()) {
5486 tgen_ensure(vertex_weights().has_value(),
5487 "wgraph: value: cannot add weighted vertices to "
5488 "vertex-unweighted graph");
5490 static_cast<int>(new_vertex_weights->size()) == k,
5491 "wgraph: value: number of vertex weights must be equal "
5492 "to number of added vertices");
5493
5494 vertex_weights_->insert(vertex_weights_->end(),
5495 new_vertex_weights->begin(),
5496 new_vertex_weights->end());
5497 } else
5498 tgen_ensure(!vertex_weights().has_value(),
5499 "wgraph: value: cannot add unweighted vertices to "
5500 "vertex-weighted graph");
5501
5502 return *this;
5503 }
5504
5505 // Adds edge (u, v).
5506 // O(log n) amortized.
5507 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
5508 ensure_adj_built();
5509 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
5510 "wgraph: value: vertex ids must be valid");
5511
5512 if (!is_directed() and u > v)
5513 std::swap(u, v);
5514
5515 if (adj_[u].count(v))
5516 return *this;
5517
5518 adj_[u].insert(v);
5519 if (!is_directed())
5520 adj_[v].insert(u);
5521 edges_.emplace_back(u, v);
5522
5523 if (w.has_value()) {
5524 tgen_ensure(edge_weights().has_value(),
5525 "wgraph: value: cannot add weighted edge to "
5526 "edge-unweighted graph");
5527
5528 edge_weights_->push_back(*w);
5529 } else
5530 tgen_ensure(!edge_weights().has_value(),
5531 "wgraph: value: cannot add unweighted edge to "
5532 "edge-weighted graph");
5533
5534 return *this;
5535 }
5536
5537 // Links graph with another `rhs`, adding the edge between u (in left
5538 // graph) and v (in right graph). Ids for added vertices are updated
5539 // accordingly.
5540 // O(rhs.n + rhs.m * log n) amortized.
5541 value &link(const value &rhs, int new_u, int new_v,
5542 std::optional<EWeight> new_w = std::nullopt) {
5543 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
5544 new_v < rhs.n(),
5545 "wgraph: value: vertex ids must be valid");
5546
5547 // Edges from right-hand side.
5548 int shift = n();
5549 add_vertices(rhs.n(), rhs.vertex_weights());
5550 for (int i = 0; i < rhs.m(); ++i) {
5551 auto [u, v] = rhs.edges()[i];
5552 add_edge(shift + u, shift + v,
5553 rhs.edge_weights().has_value()
5554 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5555 : std::nullopt);
5556 }
5557
5558 // New edge.
5559 add_edge(new_u, shift + new_v, new_w);
5560
5561 return *this;
5562 }
5563
5564 // Glues the graph with another `rhs` such that index_pairs[i].first is
5565 // considered to be the same as index_pairs[i].second. Ids for added
5566 // vertices are updated accordingly.
5567 // O(rhs.n + rhs.m * log n) amortized.
5568 value &glue(const value &rhs,
5569 std::set<std::pair<int, int>> index_pairs) {
5572 "wgraph: value: graphs must have the same is_directed value");
5573
5574 // Checks validity of indices.
5575 std::set<int> idx_left, idx_right;
5576 std::vector<int> right_id_to_left(rhs.n(), -1);
5577 for (auto [l, r] : index_pairs) {
5579 0 <= l and l < n() and 0 <= r and r < rhs.n(),
5580 "wgraph: value: vertex indices to glue must be valid");
5581 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
5582 "wgraph: value: must not have repeated indices "
5583 "on the same side to glue");
5584
5585 idx_left.insert(l);
5586 idx_right.insert(r);
5587 right_id_to_left[r] = l;
5588 }
5589
5590 // Computes new ids of right vertices.
5591 std::vector<int> new_right_id(rhs.n(), -1);
5592 int intersection_lt = 0;
5593 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5594 for (int i = 0; i < rhs.n(); ++i) {
5595 if (right_id_to_left[i] != -1) {
5596 // Is in intersection.
5597 ++intersection_lt;
5598 new_right_id[i] = right_id_to_left[i];
5599 } else {
5600 // New id.
5601 new_right_id[i] = n() + i - intersection_lt;
5602 if (rhs.vertex_weights().has_value()) {
5603 if (!rhs_vertex_weights.has_value())
5604 rhs_vertex_weights = std::vector<VWeight>();
5605 rhs_vertex_weights->push_back(
5606 (*rhs.vertex_weights())[i]);
5607 }
5608 }
5609 }
5610
5611 // Adds new vertices and edges.
5612 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5613 for (int i = 0; i < rhs.m(); ++i) {
5614 auto [u, v] = rhs.edges()[i];
5615 add_edge(new_right_id[u], new_right_id[v],
5616 rhs.edge_weights().has_value()
5617 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5618 : std::nullopt);
5619 }
5620
5621 return *this;
5622 }
5623 value &glue(const value &rhs,
5624 std::initializer_list<std::pair<int, int>> il) {
5625 return glue(rhs, std::set<std::pair<int, int>>(il));
5626 }
5627
5628 // Glues the graph with another `rhs` at `indices`. That is, idx in
5629 // `indices` are considered to be the same vertex. Ids for added
5630 // vertices are updated accordingly.
5631 // O(rhs.n + rhs.m * log n) amortized.
5632 value &glue(const value &rhs, std::set<int> indices) {
5633 std::set<std::pair<int, int>> index_pairs;
5634 for (auto i : indices)
5635 index_pairs.emplace(i, i);
5636 return glue(rhs, index_pairs);
5637 }
5638 value &glue(const value &rhs, const std::initializer_list<int> &il) {
5639 return glue(rhs, std::set<int>(il));
5640 }
5641
5642 // Disjoint union.
5643 // Shifts ids from `rhs` graph by n().
5644 // O(rhs.n + rhs.m * log n) amortized.
5646 return glue(rhs, std::set<int>());
5647 }
5648
5649 // Computes uniformly random subgraph of graph with num_edges edges.
5650 // O(n + m).
5651 value &random_subgraph(int num_edges) {
5653 num_edges <= m(),
5654 "wgraph: value: can choose at most `m` edges from graph");
5655
5656 std::vector<std::pair<int, int>> new_edges;
5657 std::optional<std::vector<EWeight>> new_edge_weights;
5658
5659 int left = m();
5660 for (int i = 0; i < m(); ++i) {
5661 if (next(1, left--) <= num_edges) {
5662 new_edges.push_back(edges()[i]);
5663 if (edge_weights_.has_value()) {
5664 if (!new_edge_weights.has_value())
5665 new_edge_weights = std::vector<EWeight>();
5666 new_edge_weights->push_back((*edge_weights())[i]);
5667 }
5668 --num_edges;
5669 }
5670 }
5671
5672 edges_ = new_edges;
5673 edge_weights_ = new_edge_weights;
5674 rebuild_adj_from_edge_list();
5675 return *this;
5676 }
5677
5678 // Computes a random (not uniform) subgraph with `num_edges` edges that
5679 // keeps every connected component connected (does not increase the
5680 // number of connected components).
5681 // 1. Picks a spanning forest via randomized Prim.
5682 // 2. Adds additional edges uniformly at random.
5683 // O(n + m).
5685 tgen_ensure(!is_directed_,
5686 "wgraph: value: random_connected_subgraph is only for "
5687 "undirected graphs");
5689 num_edges <= m(),
5690 "wgraph: value: can choose at most `m` edges from graph");
5691
5692 // Builds an incidence list: for each vertex, the (neighbor, edge
5693 // index) pairs.
5694 std::vector<std::vector<std::pair<int, int>>> incident(n());
5695 for (int i = 0; i < m(); ++i) {
5696 auto [u, v] = edges_[i];
5697 incident[u].emplace_back(v, i);
5698 incident[v].emplace_back(u, i);
5699 }
5700
5701 // Randomized Prim.
5702 std::vector<bool> vis(n(), false);
5703 std::vector<int> queue;
5704 std::vector<bool> in_tree(m(), false);
5705 int forest_edges = 0;
5706
5707 for (int start = 0; start < n(); ++start) {
5708 if (vis[start])
5709 continue;
5710 vis[start] = true;
5711 queue.push_back(start);
5712
5713 while (!queue.empty()) {
5714 int i =
5715 tgen::next<int>(0, static_cast<int>(queue.size()) - 1);
5716 int u = queue[i];
5717 std::swap(queue[i], queue.back());
5718 queue.pop_back();
5719
5720 for (auto [v, edge_idx] : incident[u]) {
5721 if (!vis[v]) {
5722 vis[v] = true;
5723 queue.push_back(v);
5724 in_tree[edge_idx] = true;
5725 ++forest_edges;
5726 }
5727 }
5728 }
5729 }
5731 num_edges >= forest_edges,
5732 "wgraph: value: random_connected_subgraph needs at least "
5733 "`n - c` edges, where `c` is the number of connected "
5734 "components");
5735
5736 // Splits edge indices into forest edges and the rest.
5737 std::vector<int> tree_idx, rest_idx;
5738 for (int i = 0; i < m(); ++i) {
5739 if (in_tree[i])
5740 tree_idx.push_back(i);
5741 else
5742 rest_idx.push_back(i);
5743 }
5744
5745 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5746
5747 std::vector<int> chosen_idx;
5748 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5749 tree_idx.end());
5750 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5751 rest_idx.begin() + num_edges - forest_edges);
5752
5753 detail::tgen_ensure_against_bug(
5754 static_cast<int>(chosen_idx.size()) == num_edges,
5755 "wgraph: value: chose a wrong number of edges");
5756
5757 std::vector<std::pair<int, int>> new_edges;
5758 std::optional<std::vector<EWeight>> new_edge_weights;
5759 if (edge_weights_.has_value())
5760 new_edge_weights = std::vector<EWeight>();
5761 for (int i : chosen_idx) {
5762 new_edges.push_back(edges_[i]);
5763 if (new_edge_weights.has_value())
5764 new_edge_weights->push_back((*edge_weights_)[i]);
5765 }
5766
5767 edges_ = new_edges;
5768 edge_weights_ = new_edge_weights;
5769 rebuild_adj_from_edge_list();
5770 return *this;
5771 }
5772
5773 // Complement. Self loops are maintained.
5774 // O(n^2).
5775 value operator!() const {
5776 tgen_ensure(!edge_weights_.has_value(),
5777 "wgraph: value: cannot compute complement of "
5778 "edge-weighted graph");
5779
5780 value complement = *this;
5781 complement.ensure_adj_built();
5782 std::vector<std::pair<int, int>> compl_edges;
5783 for (int i = 0; i < complement.n_; ++i) {
5784 std::set<int> complement_adj;
5785 for (int j = 0; j < complement.n_; ++j) {
5786 bool add_j = false;
5787 if (j == i and complement.adj_[i].count(j))
5788 add_j = true;
5789 if (j != i and !complement.adj_[i].count(j))
5790 add_j = true;
5791
5792 if (add_j) {
5793 complement_adj.insert(j);
5794 // If i > j and !is_directed(), we don't add the edge.
5795 if (i <= j or complement.is_directed_) {
5796 compl_edges.emplace_back(i, j);
5797 }
5798 }
5799 }
5800 std::swap(complement.adj_[i], complement_adj);
5801 }
5802 std::swap(complement.edges_, compl_edges);
5803
5804 return complement;
5805 }
5806
5807 // Concatenates two values.
5808 // O(N + M log N), N = n + rhs.n, M = m + rhs.m.
5809 value operator+(const value &rhs) const {
5811 "wgraph: value: graphs must have the same "
5812 "is_directed value");
5813
5814 tgen_ensure(vertex_weights().has_value() ==
5815 rhs.vertex_weights().has_value(),
5816 "wgraph: value: cannot concatenate vertex-weighted "
5817 "wgraph to unweighted");
5818 tgen_ensure(edge_weights().has_value() ==
5819 rhs.edge_weights().has_value(),
5820 "wgraph: value: cannot concatenate edge-weighted "
5821 "wgraph to unweighted");
5822
5823 value concat = *this;
5824 concat.glue(rhs, std::set<std::pair<int, int>>());
5825 concat.print_1_based_ = print_1_based_ | rhs.print_1_based_;
5826 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5827
5828 return concat;
5829 }
5830
5831 // Prints to std::ostream.
5832 // O(n + m).
5833 friend std::ostream &operator<<(std::ostream &out, const value &val) {
5834 // Prints `n` and `m`.
5835 if (val.print_nm_)
5836 out << val.n() << " " << val.m() << '\n';
5837
5838 // Prints vertex weights.
5839 if (val.vertex_weights()) {
5840 for (int i = 0; i < val.n(); ++i) {
5841 if (i > 0)
5842 out << " ";
5843 out << (*val.vertex_weights())[i];
5844 }
5845 out << '\n';
5846 }
5847
5848 // Prints edges.
5849 for (int i = 0; i < val.m(); ++i) {
5850 auto [u, v] = val.edges()[i];
5851 out << (u + val.print_1_based_) << " "
5852 << (v + val.print_1_based_);
5853
5854 // Edge weight.
5855 if (val.edge_weights().has_value())
5856 out << " " << (*val.edge_weights())[i];
5857
5858 out << '\n';
5859 }
5860
5861 return out;
5862 }
5863
5864 // Gets a std::tuple<n, m, adj> representing the value (0-based).
5865 // Unaffected by print_1_based().
5866 std::tuple<int, int, std::vector<std::set<int>>> to_std() const {
5867 ensure_adj_built();
5868 return std_type(n_, m(), adj_);
5869 }
5870
5871 // Gets a 1-based (n, m, adj): labels +1, adj size n+1, index 0 unused.
5872 // Unaffected by print_1_based().
5873 std::tuple<int, int, std::vector<std::set<int>>>
5875 ensure_adj_built();
5876 std::vector<std::set<int>> adj(n_ + 1);
5877 for (int u = 0; u < n_; ++u)
5878 for (int v : adj_[u])
5879 adj[u + 1].insert(v + 1);
5880 return std_type(n_, m(), adj);
5881 }
5882
5883 private:
5884 // Rebuilds adjacency from edges_ after replacing the edge list (e.g.
5885 // subgraph operations).
5886 // O(m log n).
5887 void rebuild_adj_from_edge_list() {
5888 adj_.assign(n_, {});
5889 for (auto [u, v] : edges_) {
5890 adj_[u].insert(v);
5891 if (!is_directed_)
5892 adj_[v].insert(u);
5893 }
5894 adj_built_ = true;
5895 }
5896
5897 // Builds adj_ from edges_ on first use.
5898 // O(1) if already built; O(m log n) otherwise.
5899 void ensure_adj_built() const {
5900 if (adj_built_)
5901 return;
5902 const_cast<value *>(this)->rebuild_adj_from_edge_list();
5903 }
5904 };
5905
5906 // Adds all edges from `rhs` as preset edges.
5907 // O(rhs.m * log m).
5909 tgen_ensure(is_directed_ == rhs.is_directed(),
5910 "wgraph: graphs must have the same is_directed value");
5911
5912 for (auto [u, v] : rhs.edges())
5913 add_edge(u, v);
5914 return *this;
5915 }
5916
5917 // Generates graph value.
5918 // Optimized for performance: dense no-preset graphs use index sampling;
5919 // otherwise gen_remaining_edges.
5920 // O(n + m log^2 n) expected.
5921 value gen() const {
5922 detail::tgen_ensure_against_bug(static_cast<int>(edges_.size()) <= m_,
5923 "wgraph: too many edges were added");
5924
5925 // All edges already added.
5926 if (static_cast<int>(edges_.size()) == m_)
5927 return value(n_, edges_, is_directed_);
5928
5929 // Splits into two cases to optimize performance.
5930
5931 // No presets and m > max_edges / 2: sample m distinct edge indices.
5932 if (auto indexed = try_gen_by_edge_index())
5933 return *indexed;
5934
5935 // Otherwise: fill preset edges up to m_ with uniform random edges.
5936 return gen_remaining_edges(
5937 std::vector<std::pair<int, int>>(edges_.begin(), edges_.end()));
5938 }
5939
5940 // Gets a (not uniformly) random connected undirected graph.
5941 // 1. Preset edges induce a spanning forest on their components.
5942 // 2. Then, uniformly random edges between components are added.
5943 // 3. Remaining edges are added uniformly at random.
5944 // O(n + m log^2 n) expected.
5946 tgen_ensure(!is_directed_,
5947 "wgraph: get_connected is only for undirected graphs");
5948 tgen_ensure(m_ >= n_ - 1,
5949 "wgraph: connected graph needs at least n - 1 edges");
5950
5951 std::vector<std::pair<int, int>> edges;
5952 edges.reserve(m_);
5953
5954 if (edges_.empty()) {
5955 if (n_ > 1) {
5956 std::vector<int> prufer(n_ - 2);
5957 for (int i = 0; i < n_ - 2; ++i)
5958 prufer[i] = next<int>(0, n_ - 1);
5959 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5960 edges.emplace_back(u, v);
5961 }
5962 } else {
5963 edges.assign(edges_.begin(), edges_.end());
5964
5965 std::vector<std::vector<int>> adj(n_);
5966 for (auto [u, v] : edges_) {
5967 adj[u].push_back(v);
5968 adj[v].push_back(u);
5969 }
5970
5971 std::vector<int> comp_size;
5972 std::vector<std::vector<int>> component_ids;
5973 std::vector<bool> vis(n_, false);
5974 std::queue<int> q;
5975
5976 for (int i = 0; i < n_; ++i) {
5977 if (vis[i])
5978 continue;
5979
5980 vis[i] = true;
5981 q.push(i);
5982 comp_size.push_back(0);
5983 component_ids.emplace_back();
5984 while (q.size()) {
5985 int u = q.front();
5986 q.pop();
5987 ++comp_size.back();
5988 component_ids.back().push_back(u);
5989 for (int v : adj[u]) {
5990 if (!vis[v]) {
5991 vis[v] = true;
5992 q.push(v);
5993 }
5994 }
5995 }
5996 }
5997
5998 if (component_ids.size() > 1) {
5999 std::vector<int> prufer_values = many_by_distribution(
6000 static_cast<int>(component_ids.size()) - 2, comp_size);
6001 for (auto [u, v] :
6002 detail::edges_from_prufer(std::move(prufer_values)))
6003 edges.emplace_back(pick(component_ids[u]),
6004 pick(component_ids[v]));
6005 }
6006 }
6007
6008 return gen_remaining_edges(std::move(edges));
6009 }
6010
6011 // Gets a (not uniformly) random directed acyclic graph.
6012 // 1. Randomized Kahn (uniform choice among indegree-0 vertices) yields a
6013 // random topological order of the preset edges (which must be acyclic).
6014 // 2. Extra edges are sampled randomly using the order.
6015 // With no preset edges: sample a random graph then orient acyclically.
6016 // Optimized for performance (distinct upper-triangle edge-index sampling;
6017 // rejection instead of pair::distinct for preset edges).
6018 // O(n + m log^2 n) expected.
6020 tgen_ensure(is_directed_,
6021 "wgraph: get_acyclic is only for directed graphs");
6022
6023 if (edges_.empty()) {
6024 std::vector<int> order(n_);
6025 std::iota(order.begin(), order.end(), 0);
6026 for (int i = n_ - 1; i > 0; --i)
6027 std::swap(order[i], order[next(0, i)]);
6028
6029 const long long max_pairs =
6030 static_cast<long long>(n_) * (n_ - 1) / 2;
6031 tgen_ensure(m_ <= max_pairs,
6032 "wgraph: not enough edges to generate");
6033
6034 std::vector<std::pair<int, int>> edges;
6035 edges.reserve(m_);
6036 for (long long idx : distinct_range<long long>(0, max_pairs - 1)
6037 .gen_list(m_)
6038 .to_std()) {
6039 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
6040 edges.emplace_back(order[i], order[j]);
6041 }
6042 return value(n_, edges, true);
6043 }
6044
6045 std::vector<std::vector<int>> adj(n_);
6046 std::vector<int> indeg(n_, 0);
6047 for (auto [u, v] : edges_) {
6048 adj[u].push_back(v);
6049 ++indeg[v];
6050 }
6051
6052 std::vector<int> available;
6053 for (int i = 0; i < n_; ++i)
6054 if (indeg[i] == 0)
6055 available.push_back(i);
6056
6057 // Random topological order using randomized Kahn's algorithm.
6058 std::vector<int> order;
6059 while (!available.empty()) {
6060 int idx = next(0, static_cast<int>(available.size()) - 1);
6061 int u = available[idx];
6062 std::swap(available[idx], available.back());
6063 available.pop_back();
6064
6065 order.push_back(u);
6066 for (int v : adj[u])
6067 if (--indeg[v] == 0)
6068 available.push_back(v);
6069 }
6070
6071 tgen_ensure(static_cast<int>(order.size()) == n_,
6072 "wgraph: preset edges contain a directed cycle");
6073
6074 value acyclic(n_, edges_, true);
6075
6076 // Generates final edges.
6077
6078 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6079 "wgraph: too many edges were added");
6080
6081 if (acyclic.m() < m_) {
6082 std::vector<int> order_pos(n_);
6083 for (int i = 0; i < n_; ++i)
6084 order_pos[order[i]] = i;
6085
6086 std::unordered_set<uint64_t> seen;
6087 seen.reserve(m_ * 2);
6088 for (auto [u, v] : acyclic.edges())
6089 seen.insert(
6090 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6091
6092 const long long max_pairs =
6093 static_cast<long long>(n_) * (n_ - 1) / 2;
6094 while (acyclic.m() < m_) {
6095 std::pair<int, int> edge;
6096 if (!detail::try_generate_distinct(seen, [&] {
6097 long long idx = next<long long>(0, max_pairs - 1);
6098 edge = detail::decode_undirected_simple_edge(n_, idx);
6099 return detail::undirected_edge_key(edge.first,
6100 edge.second);
6101 }))
6102 throw detail::error("wgraph: not enough edges to generate");
6103 acyclic.add_edge(order[edge.first], order[edge.second]);
6104 }
6105 }
6106
6107 return acyclic;
6108 }
6109
6110 // Generates a (not uniformly) random skewed connected graph.
6111 // 1. Builds the same skewed labeled tree as wtree::gen_skewed(n,
6112 // elongation)(root 0, parent(i) = wnext(i, elongation) for i >= 1).
6113 // If is_directed, tree edges are oriented down the tree.
6114 // 2. Adds the remaining edges: pick an endpoint u uniformly;
6115 // pick k uniformly in [1, spread]; walk from u toward the root k
6116 // times along tree parents to get v; add edge (v, u).
6117 // If elongation is small, generates a graph with small diameter.
6118 // If elongation is large, generates a graph with large diameter, with
6119 // vertices 0 and n-1 being far apart.
6120 // O(n + m log n) if spread is O(1);
6121 // O(n log n + m log^2 n) expected otherwise.
6122 static value gen_skewed(int n, int m, int elongation, int spread,
6123 bool is_directed = false) {
6125 m >= n - 1,
6126 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6127 tgen_ensure(spread >= 2,
6128 "wgraph: gen_skewed spread must be at least 2");
6129
6130 value skewed(n, {}, is_directed);
6131
6132 std::vector<int> parent(n), depth(n, 0);
6133 parent[0] = 0;
6134 for (int i = 1; i < n; ++i) {
6135 int p = wnext<int>(i, elongation);
6136 parent[i] = p;
6137 depth[i] = depth[p] + 1;
6138 skewed.add_edge(p, i);
6139 }
6140
6141 const int extra = m - (n - 1);
6142 if (extra == 0)
6143 return skewed;
6144
6145 // If spread is large, use binary lifting to find the ancestor.
6146 // Otherwise, enumerate O(n * spread) ancestor edges and sample
6147 // directly.
6148 constexpr int naive_ancestor_spread = 20;
6149
6150 if (spread <= naive_ancestor_spread) {
6151 std::vector<std::pair<int, int>> candidates;
6152 candidates.reserve(n * spread);
6153 for (int u = 0; u < n; ++u) {
6154 int max_k = std::min(spread, depth[u]);
6155 if (max_k < 2)
6156 continue;
6157 int v = parent[u];
6158 for (int k = 2; k <= max_k; ++k) {
6159 v = parent[v];
6160 candidates.emplace_back(v, u);
6161 }
6162 }
6163
6164 tgen_ensure(extra <= static_cast<int>(candidates.size()),
6165 "wgraph: not enough edges to generate");
6166
6167 for (auto [v, u] : choose(candidates, extra))
6168 skewed.add_edge(v, u);
6169 } else {
6170 // Binary lifting.
6171 int lg = 1;
6172 while ((1 << lg) <= n)
6173 ++lg;
6174
6175 std::vector<std::vector<int>> up(lg, std::vector<int>(n));
6176 for (int v = 0; v < n; ++v)
6177 up[0][v] = parent[v];
6178 for (int j = 1; j < lg; ++j)
6179 for (int v = 0; v < n; ++v)
6180 up[j][v] = up[j - 1][up[j - 1][v]];
6181
6182 // Creates uniform generator of edges (u, v) such that v is ancestor
6183 // of u. For that, every u has depth[u]-1 choices for v, so we
6184 // weight u by min(spread - 1, depth[u] - 1). After that we can
6185 // just pick the ancestor uniformly.
6186 std::vector<int> distribution = depth;
6187 for (int &d : distribution)
6188 d = std::max(0, std::min(spread - 1, d - 1));
6189 weighted_sampler vertex_choice(distribution);
6190 distinct extra_edges([&]() -> std::pair<int, int> {
6191 int u = static_cast<int>(vertex_choice.next());
6192 int k = next(2, spread);
6193 int v = u;
6194 for (int j = 0; j < lg; ++j)
6195 if (k >> j & 1)
6196 v = up[j][v];
6197 return {v, u};
6198 });
6199
6200 while (skewed.m() < m) {
6201 std::pair<int, int> edge;
6202 try {
6203 edge = extra_edges.gen();
6204 } catch (const std::runtime_error &e) {
6205 if (std::string(e.what()) ==
6206 "tgen: distinct: no more distinct values")
6207 throw detail::error(
6208 "wgraph: not enough edges to generate");
6209 throw e;
6210 }
6211
6212 skewed.add_edge(edge.first, edge.second);
6213 }
6214 }
6215
6216 return skewed;
6217 }
6218
6219 // Generates a random bipartite graph. The first side has vertices
6220 // 0 .. n1-1, the second n1 .. n1+n2-1.
6221 // Uniform when connected is false (distinct cross-edge indices).
6222 // When connected, incremental bipartite spanning tree + rejection fill;
6223 // not uniform over connected bipartite graphs.
6224 // O(n1 + n2 + m log(n1 * n2)) expected.
6225 static value gen_bipartite(int n1, int n2, int m, bool connected = false) {
6226 tgen_ensure(m >= 0, "wgraph: number of edges must be nonnegative");
6227 long long num_edges = 1LL * n1 * n2;
6228 tgen_ensure(m <= num_edges,
6229 "wgraph: bipartite graph has at most n1 * n2 edges");
6230 if (connected)
6232 m >= n1 + n2 - 1,
6233 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6234 "edges");
6235
6236 // Samples distinct cross edges uniformly.
6237 if (!connected) {
6238 std::vector<std::pair<int, int>> edges;
6239 edges.reserve(m);
6240 for (long long idx : distinct_range<long long>(0, num_edges - 1)
6241 .gen_list(m)
6242 .to_std())
6243 edges.emplace_back(static_cast<int>(idx / n2),
6244 n1 + static_cast<int>(idx % n2));
6245 return value(n1 + n2, std::move(edges), false);
6246 }
6247
6248 std::unordered_set<uint64_t> used_edges;
6249 used_edges.reserve(m * 2);
6250 std::vector<std::pair<int, int>> edges;
6251 edges.reserve(m);
6252
6253 auto pack_edge = [](int u, int v) -> uint64_t {
6254 if (u > v)
6255 std::swap(u, v);
6256 return (static_cast<uint64_t>(u) << 32) | static_cast<uint32_t>(v);
6257 };
6258
6259 // Creates a spanning tree.
6260 if (n1 > 0 and n2 > 0) {
6261 std::vector<int> left = {next(0, n1 - 1)};
6262 std::vector<int> right = {next(n1, n1 + n2 - 1)};
6263 std::vector<int> remaining;
6264 left.reserve(n1);
6265 right.reserve(n2);
6266 remaining.reserve(n1 + n2 - 2);
6267
6268 for (int u = 0; u < n1; ++u)
6269 if (u != left[0])
6270 remaining.push_back(u);
6271 for (int v = n1; v < n1 + n2; ++v)
6272 if (v != right[0])
6273 remaining.push_back(v);
6274 shuffle(remaining.begin(), remaining.end());
6275
6276 auto add_tree_edge = [&](int u, int v) {
6277 used_edges.insert(pack_edge(u, v));
6278 edges.emplace_back(u, v);
6279 };
6280 add_tree_edge(left[0], right[0]);
6281
6282 for (int vertex : remaining) {
6283 if (vertex < n1) {
6284 add_tree_edge(vertex, pick(right));
6285 left.push_back(vertex);
6286 } else {
6287 add_tree_edge(pick(left), vertex);
6288 right.push_back(vertex);
6289 }
6290 }
6291 detail::tgen_ensure_against_bug(
6292 used_edges.size() == size_t(n1 + n2 - 1),
6293 "wgraph: invalid bipartite spanning tree size");
6294 }
6295
6296 // Adds remaining edges.
6297 while (edges.size() < size_t(m)) {
6298 int u = next(0, n1 - 1);
6299 int v = next(n1, n1 + n2 - 1);
6300 if (used_edges.insert(pack_edge(u, v)).second)
6301 edges.emplace_back(u, v);
6302 }
6303
6304 return value(n1 + n2, std::move(edges), false);
6305 }
6306
6307 // Random graph on n vertices; each admissible edge independently with
6308 // probability p. Equivalent to sampling m ~ Binomial(N, p) then a uniform
6309 // G(n, m), where N is the number of admissible edges for the given
6310 // directed / self-loop mode.
6311 // O(n^2 (1 + p log^2 n)) expected.
6312 static value gen_np(int n, double p, bool is_directed = false,
6313 bool has_self_loops = false) {
6314 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
6315 tgen_ensure(p >= 0 and p <= 1, "wgraph: probability must be in [0, 1]");
6316
6317 long long max_edges =
6318 detail::max_graph_edges(n, is_directed, has_self_loops);
6319
6320 long long m = 0;
6321 if (p == 1.0)
6322 m = max_edges;
6323 else if (p > 0.0)
6324 for (long long i = 0; i < max_edges; ++i)
6325 if (next<double>(0.0, 1.0) < p)
6326 ++m;
6327
6328 tgen_ensure(m <= std::numeric_limits<int>::max(),
6329 "wgraph: too many edges to generate");
6330 return wgraph(n, static_cast<int>(m), is_directed, has_self_loops)
6331 .gen();
6332 }
6333
6334 private:
6335 // If this generator has no preset edges and m is large relative to the
6336 // maximum edge count, sample by distinct edge index. Otherwise
6337 // std::nullopt.
6338 // Optimized for performance (index sampling instead of rejection).
6339 // O(m log n).
6340 std::optional<value> try_gen_by_edge_index() const {
6341 if (!edges_.empty())
6342 return std::nullopt;
6343
6344 long long max_edges =
6345 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6346 if (m_ > max_edges)
6347 throw detail::error("wgraph: not enough edges to generate");
6348 if (max_edges <= 0 or 2LL * m_ <= max_edges)
6349 return std::nullopt;
6350
6351 std::vector<std::pair<int, int>> edges;
6352 edges.reserve(m_);
6353 for (long long idx :
6354 distinct_range<long long>(0, max_edges - 1).gen_list(m_).to_std())
6355 edges.push_back(detail::decode_graph_edge_index(
6356 n_, idx, is_directed_, has_self_loops_));
6357
6358 return value(n_, edges, is_directed_);
6359 }
6360
6361 // Fills `edges` up to m_ with uniform random edges not already present.
6362 // Optimized for performance (uint64 edge keys + try_generate_distinct).
6363 // O(m log^2 n) expected.
6364 value gen_remaining_edges(std::vector<std::pair<int, int>> edges) const {
6365 detail::tgen_ensure_against_bug(static_cast<int>(edges.size()) <= m_,
6366 "wgraph: too many edges were added");
6367
6368 if (static_cast<int>(edges.size()) == m_)
6369 return value(n_, edges, is_directed_);
6370
6371 edges.reserve(m_);
6372
6373 std::unordered_set<uint64_t> seen;
6374 seen.reserve(m_ * 2);
6375 for (auto [u, v] : edges) {
6376 if (!is_directed_ and u > v)
6377 std::swap(u, v);
6378 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6379 : detail::undirected_edge_key(u, v));
6380 }
6381
6382 while (static_cast<int>(edges.size()) < m_) {
6383 std::pair<int, int> edge;
6384 if (!detail::try_generate_distinct(seen, [&] {
6385 edge = detail::get_random_graph_edge(n_, is_directed_,
6386 has_self_loops_);
6387 if (!is_directed_ and edge.first > edge.second)
6388 std::swap(edge.first, edge.second);
6389 return is_directed_ ? detail::directed_edge_key(edge.first,
6390 edge.second)
6391 : detail::undirected_edge_key(
6392 edge.first, edge.second);
6393 }))
6394 throw detail::error("wgraph: not enough edges to generate");
6395 edges.emplace_back(edge);
6396 }
6397
6398 return value(n_, edges, is_directed_);
6399 }
6400};
6401
6402// Implementation of wtree::value constructor from wgraph.
6403// O(n + m alpha(n)).
6404template <typename VWeight, typename EWeight>
6405wtree<VWeight, EWeight>::value::value(
6406 const typename wgraph<VWeight, EWeight>::value &g)
6407 : n_(g.n()), adj_(g.n()), print_1_based_(false), print_n_(false),
6408 dsu_(g.n()) {
6409 tgen_ensure(g.n() > 0, "wtree: value: graph must have at least one vertex");
6410 tgen_ensure(!g.is_directed(),
6411 "wtree: value: graph must be undirected to form a tree");
6412
6413 if (g.vertex_weights().has_value())
6414 vertex_weights_ = *g.vertex_weights();
6415 if (g.edge_weights().has_value())
6416 edge_weights_ = std::vector<EWeight>();
6417
6418 if (n_ == 1)
6419 return;
6420
6421 std::vector<int> order(g.m());
6422 std::iota(order.begin(), order.end(), 0);
6423 tgen::shuffle(order.begin(), order.end());
6424
6425 std::vector<std::pair<int, int>> tree_edges;
6426 tree_edges.reserve(n_ - 1);
6427
6428 for (int i : order) {
6429 auto [u, v] = g.edges()[i];
6430 if (!dsu_.unite(u, v))
6431 continue;
6432 if (u > v)
6433 std::swap(u, v);
6434
6435 tree_edges.emplace_back(u, v);
6436 adj_[u].insert(v);
6437 adj_[v].insert(u);
6438 if (edge_weights_.has_value())
6439 edge_weights_->push_back((*g.edge_weights())[i]);
6440 if (static_cast<int>(tree_edges.size()) == n_ - 1)
6441 break;
6442 }
6443
6444 tgen_ensure(static_cast<int>(tree_edges.size()) == n_ - 1,
6445 "wtree: value: graph must be connected to form a tree");
6446
6447 edges_ = std::move(tree_edges);
6448}
6449
6450/*
6451 * Other types of weighted-ness.
6452 */
6453
6454// Vertex weighted graph.
6455template <typename VWeight> using vgraph = wgraph<VWeight, int>;
6456
6457// Edge weighted graph.
6458template <typename EWeight> using egraph = wgraph<int, EWeight>;
6459
6460// Unweighted graph.
6461using graph = wgraph<int, int>;
6462
6463/*
6464 * Standard graphs.
6465 */
6466
6467// Complete.
6468// O(n^2).
6469inline graph::value K(int n) { return graph(n, n * (n - 1) / 2).gen(); }
6470
6471// Path.
6472// Path with `n` vertices. The edges of the path are 0 and n-1.
6473// If directed, edges are i -> i+1 for i in [0, n-2).
6474// O(n).
6475inline graph::value P(int n, bool is_directed = false) {
6476 graph g(n, n - 1, is_directed);
6477 for (int i = 0; i + 1 < n; ++i)
6478 g.add_edge(i, i + 1);
6479 return g.gen();
6480}
6481
6482// Cycle.
6483// n >= 3.
6484// If directed, edges are i -> (i+1) % n.
6485// O(n).
6486inline graph::value C(int n, bool is_directed = false) {
6487 tgen_ensure(n >= 3, "graph: cycle size must be at least 3");
6488
6489 graph g(n, n, is_directed);
6490 for (int i = 0; i < n; ++i)
6491 g.add_edge(i, (i + 1) % n);
6492 return g.gen();
6493}
6494
6495// Complete bipartite.
6496// The first side has vertices `0` to `n1-1`, the second side has vertices `n1`
6497// to `n1+n2-1`.
6498// O(n1 * n2).
6499inline graph::value K(int n1, int n2) {
6500 graph g(n1 + n2, static_cast<long long>(n1) * n2);
6501 for (int i = 0; i < n1; ++i)
6502 for (int j = 0; j < n2; ++j)
6503 g.add_edge(i, n1 + j);
6504 return g.gen();
6505}
6506
6507// Star.
6508// The center is vertex 0.
6509// O(n).
6510inline graph::value S(int n) { return K(1, n - 1); }
6511
6512/****************
6513 * *
6514 * GEOMETRY *
6515 * *
6516 ****************/
6517
6518namespace geometry {
6519
6520// Point on the plane with coordinates of type T.
6521template <typename T> struct point {
6522 static_assert(std::is_arithmetic_v<T>,
6523 "point requires an arithmetic coordinate type");
6524
6525 // Dot/cross product type: __int128 for T = long long, long long for other
6526 // integral T, T for floating-point.
6527 using product_t = std::conditional_t<
6528 std::is_same_v<T, long long>, detail::i128,
6529 std::conditional_t<std::is_integral_v<T>, long long, T>>;
6530
6531 // x and y coordinates.
6532 T x_, y_;
6533
6534 // Constructs a point with coordinates x and y.
6535 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6536
6537 // Returns the x coordinate.
6538 T x() const { return x_; }
6539
6540 // Returns the y coordinate.
6541 T y() const { return y_; }
6542
6543 // Equality of coordinates, with epsilon-based equality for floating-point
6544 // coordinates (tolerance 1e-9).
6545 static bool coord_eq(T a, T b) {
6546 if constexpr (std::is_integral_v<T>)
6547 return a == b;
6548 constexpr T eps = T(1e-9);
6549 T d = a - b;
6550 return d >= -eps and d <= eps;
6551 }
6552
6553 // Lexicographic order (by x, then y).
6554 bool operator<(const point &p) const {
6555 if (!coord_eq(x_, p.x()))
6556 return x_ < p.x();
6557 return y_ < p.y();
6558 }
6559
6560 // Equality of coordinates.
6561 bool operator==(const point &p) const {
6562 return coord_eq(x_, p.x()) and coord_eq(y_, p.y());
6563 }
6564
6565 // Vector addition.
6566 point operator+(const point &p) const {
6567 return point(x_ + p.x(), y_ + p.y());
6568 }
6569
6570 // Vector subtraction.
6571 point operator-(const point &p) const {
6572 return point(x_ - p.x(), y_ - p.y());
6573 }
6574
6575 // Scalar multiplication.
6576 point operator*(T c) const { return point(x_ * c, y_ * c); }
6577
6578 // Dot product.
6579 product_t operator*(const point &p) const {
6580 if constexpr (std::is_floating_point_v<T>)
6581 return x_ * p.x() + y_ * p.y();
6582 return product_t(x_) * p.x() + product_t(y_) * p.y();
6583 }
6584
6585 // Cross product (signed area of the parallelogram).
6586 product_t operator^(const point &p) const {
6587 if constexpr (std::is_floating_point_v<T>)
6588 return x_ * p.y() - y_ * p.x();
6589 return product_t(x_) * p.y() - product_t(y_) * p.x();
6590 }
6591
6592 // Prints the point as "x y".
6593 friend std::ostream &operator<<(std::ostream &out, const point &p) {
6594 return out << p.x() << ' ' << p.y();
6595 }
6596};
6597
6598// Generates n distinct integer points in [min_coord, max_coord]^2 with no three
6599// collinear.
6600// O(n).
6601inline std::vector<point<long long>>
6602random_points_general_position(int n, long long min_coord,
6603 long long max_coord) {
6604 tgen_ensure(n > 0,
6605 "geometry: random_points_general_position: n must be positive");
6606 tgen_ensure(max_coord >= min_coord,
6607 "geometry: random_points_general_position: min_coord must be "
6608 "at most max_coord");
6610 static_cast<detail::i128>(max_coord) - min_coord <=
6611 std::numeric_limits<long long>::max(),
6612 "geometry: random_points_general_position: coordinate range too large");
6613 uint64_t width = max_coord - min_coord;
6614 uint64_t p = math::prime_from(2 * n);
6615
6616 // Requires width >= p - 1 because sheared coordinates lie in [0, p - 1].
6617 tgen_ensure(width >= p - 1,
6618 "geometry: random_points_general_position: coordinate range "
6619 "too small for n");
6620
6621 // Base set: (x, x^-1 mod p) for x = 1, ..., p - 1.
6622 //
6623 // For a line ax + by + c = 0, substituting y = x^-1 gives ax^2 + cx + b = 0
6624 // (for x != 0), a quadratic with at most two roots in F_p. So at most two
6625 // base points lie on any line. x |-> x^-1 is bijective on {1, ..., p - 1},
6626 // so all points are distinct and no three are collinear.
6627 std::vector<uint64_t> x_range(p - 1);
6628 std::iota(x_range.begin(), x_range.end(), 1);
6629 shuffle(x_range.begin(), x_range.end());
6630 std::vector<detail::i128> bx(n), by(n);
6631 for (int i = 0; i < n; ++i) {
6632 uint64_t x = x_range[i];
6633 bx[i] = x;
6634 by[i] = math::modular_inverse(x, p);
6635 }
6636
6637 // Randomize placement without breaking general position: compose elementary
6638 // shears in SL(2, F_p), each either [1 r; 0 1] or [1 0; r 1] with
6639 // r in {-2, -1, 1, 2} (mod p). Every shear has determinant 1, so their
6640 // product is invertible. Invertible linear maps preserve collinearity, so
6641 // the image still has no three collinear points.
6642 const int num_shears = 8;
6643 std::vector<detail::i128> lin_x = bx, lin_y = by;
6644
6645 for (int it = 0; it < num_shears; ++it) {
6646 bool vertical_shear = next(2) == 0;
6647 int shear_r = pick({-2, -1, 1, 2});
6648
6649 for (int i = 0; i < n; ++i) {
6650 if (vertical_shear)
6651 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6652 else
6653 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6654
6655 if (lin_x[i] < 0)
6656 lin_x[i] += p;
6657 if (lin_y[i] < 0)
6658 lin_y[i] += p;
6659 }
6660 }
6661
6662 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6663 max_y = lin_y[0];
6664 for (int i = 1; i < n; ++i) {
6665 min_x = std::min(min_x, lin_x[i]);
6666 max_x = std::max(max_x, lin_x[i]);
6667 min_y = std::min(min_y, lin_y[i]);
6668 max_y = std::max(max_y, lin_y[i]);
6669 }
6670
6671 detail::i128 x_shift =
6672 min_coord - min_x +
6673 next<uint64_t>(0, static_cast<uint64_t>(width - (max_x - min_x)));
6674 detail::i128 y_shift =
6675 min_coord - min_y +
6676 next<uint64_t>(0, static_cast<uint64_t>(width - (max_y - min_y)));
6677
6678 std::vector<point<long long>> pts;
6679 for (int i = 0; i < n; ++i)
6680 pts.emplace_back(static_cast<long long>(lin_x[i] + x_shift),
6681 static_cast<long long>(lin_y[i] + y_shift));
6682 return pts;
6683}
6684
6685namespace detail {
6686
6687using i128 = tgen::detail::i128;
6688
6689// Signed area of triangle (a, b, p); positive iff (a, b, p) are in
6690// counterclockwise order. 0 iff (a, b, p) are collinear. O(1).
6691inline i128 ccw(const point<long long> &a, const point<long long> &b,
6692 const point<long long> &p) {
6693 return (static_cast<i128>(b.x()) - a.x()) *
6694 (static_cast<i128>(p.y()) - a.y()) -
6695 (static_cast<i128>(b.y()) - a.y()) *
6696 (static_cast<i128>(p.x()) - a.x());
6697}
6698
6699// Integer projection of P onto line AB (A and B need not be distinct).
6700inline i128 proj_on_ab(const point<long long> &P, const point<long long> &A,
6701 const point<long long> &B) {
6702 return (P - A) * (B - A);
6703}
6704
6705// In-place Hamiltonian path on points[left..right-1] with points[left]
6706// start and points[right-1] end.
6707// O(n log n) expected if points are "random", O(n^2) worst case.
6708inline void conquer(std::vector<point<long long>> &points, int left,
6709 int right) {
6710 if (right - left <= 3)
6711 return;
6712
6713 point<long long> A = points[left], B = points[right - 1];
6714
6715 // If all points are collinear, sort them properly and return.
6716 bool all_collinear = true;
6717 for (int k = left + 1; k < right - 1; ++k) {
6718 if (ccw(A, B, points[k]) != 0) {
6719 all_collinear = false;
6720 break;
6721 }
6722 }
6723 if (all_collinear) {
6724 std::sort(points.begin() + left, points.begin() + right,
6725 [&](const point<long long> &P, const point<long long> &Q) {
6726 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6727 });
6728 return;
6729 }
6730
6731 // Choses a pivot that is not collinear with A and B.
6732 std::vector<int> candidates;
6733 for (int k = left + 1; k < right - 1; ++k) {
6734 if (ccw(A, B, points[k]) != 0)
6735 candidates.push_back(k);
6736 }
6737 int ci = candidates[next(0, static_cast<int>(candidates.size()) - 1)];
6738 point<long long> C = points[ci];
6739
6740 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6741 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6742 bool a_on_positive = ccw(C, A, B) < 0;
6743
6744 // Classify interior points into two sides of the wedge A-C-B for partition.
6745 // Collinear points on AB are tie-broken along the segment.
6746 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6747 auto is_positive = [&](const point<long long> &P) -> bool {
6748 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6749 // Weighted wedge side of P w.r.t. C, A, B.
6750 if (s != 0)
6751 return s > 0;
6752 // P is on line AB: split by projection past the midpoint.
6753 return 2 * proj_on_ab(P, A, B) > proj_sum;
6754 };
6755
6756 // Holds C at points[right-2] while classifying interior points in
6757 // [left+1, right-3].
6758 if (ci != right - 2)
6759 std::swap(points[ci], points[right - 2]);
6760
6761 int i = left + 1;
6762 int j = right - 3;
6763 while (i < j) {
6764 if (is_positive(points[i]) == a_on_positive)
6765 ++i;
6766 else if (is_positive(points[j]) != a_on_positive)
6767 --j;
6768 else {
6769 std::swap(points[i], points[j]);
6770 ++i;
6771 --j;
6772 }
6773 }
6774
6775 // After partition:
6776 // points[left]=A | (A,C)... | C | (C,B)... | points[right-1]=B.
6777
6778 // After the swap, p is the index of C (pivot between the two subpaths).
6779 int p = i;
6780 if (i == j and is_positive(points[i]) == a_on_positive)
6781 ++p;
6782 std::swap(points[p], points[right - 2]);
6783
6784 // Path A -> C.
6785 conquer(points, left, p + 1);
6786 // Path C -> B.
6787 conquer(points, p, right);
6788}
6789
6790// Samples k sorted distinct integers from [left, right] uniformly.
6791// Optimized for performance (pool partial Fisher–Yates or complement path for
6792// modest ranges; sparse-map fallback otherwise).
6793// O(k log k); O(right - left) memory when the range is modest.
6794inline std::vector<long long>
6795sample_sorted_distinct_in_range(int k, long long left, long long right) {
6796 long long universe = right - left + 1;
6797 std::vector<long long> res;
6798 res.reserve(k);
6799 if (k == 0)
6800 return res;
6801
6802 constexpr long long pool_threshold = 8'000'000;
6803 constexpr long long pool_always_below = 500'000;
6804
6805 if (universe <= pool_threshold and
6806 (universe <= pool_always_below or k >= universe / 4)) {
6807 size_t u = universe;
6808 size_t ks = k;
6809 std::vector<long long> pool(u);
6810 std::iota(pool.begin(), pool.end(), left);
6811 size_t m = ks <= u / 2 ? ks : u - ks;
6812 for (size_t i = 0; i < m; ++i) {
6813 size_t j = next<size_t>(i, u - 1);
6814 std::swap(pool[i], pool[j]);
6815 }
6816 if (ks <= u / 2) {
6817 res.assign(pool.begin(), pool.begin() + ks);
6818 std::sort(res.begin(), res.end());
6819 } else {
6820 std::vector<char> excluded(u, 0);
6821 for (size_t i = 0; i < m; ++i)
6822 excluded[pool[i] - left] = 1;
6823 for (long long v = left; v <= right; ++v)
6824 if (!excluded[v - left])
6825 res.push_back(v);
6826 }
6827 } else {
6828 std::unordered_map<long long, long long> virtual_list;
6829 virtual_list.reserve(k * 2);
6830 for (long long i = 0; i < k; ++i) {
6831 long long j = next<long long>(i, universe - 1);
6832 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6833 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6834 virtual_list[j] = vi;
6835 virtual_list[i] = vj;
6836 res.push_back(virtual_list[i] + left);
6837 }
6838 std::sort(res.begin(), res.end());
6839 }
6840 return res;
6841}
6842
6843// Valtr-style signed edge components along one axis from n sorted distinct
6844// coordinates. The n differences sum to zero.
6845inline std::vector<long long>
6846valtr_edge_components(const std::vector<long long> &sorted_coords) {
6847 int n = static_cast<int>(sorted_coords.size());
6848 std::vector<long long> left, right;
6849 left.reserve(n / 2);
6850 right.reserve(n / 2);
6851 for (int i = 1; i + 1 < n; ++i) {
6852 if (next(2) == 0)
6853 left.push_back(sorted_coords[i]);
6854 else
6855 right.push_back(sorted_coords[i]);
6856 }
6857 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6858 std::vector<long long> seq;
6859 seq.reserve(n + 1);
6860 seq.push_back(lo);
6861 for (long long v : left)
6862 seq.push_back(v);
6863 seq.push_back(hi);
6864 for (auto it = right.rbegin(); it != right.rend(); ++it)
6865 seq.push_back(*it);
6866 seq.push_back(lo);
6867 std::vector<long long> comps(n);
6868 for (int i = 0; i < n; ++i)
6869 comps[i] = seq[i + 1] - seq[i];
6870 return comps;
6871}
6872
6873// Drops boundary vertices that are collinear with their cyclic neighbors.
6874// O(m), m = |points|.
6875inline std::vector<point<long long>>
6876simplify_strict_boundary(std::vector<point<long long>> points) {
6877 int n = static_cast<int>(points.size());
6878 if (n < 3)
6879 return points;
6880
6881 std::vector<point<long long>> strict_points;
6882 strict_points.reserve(n);
6883 for (int i = 0; i < n; ++i) {
6884 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6885 strict_points.push_back(points[i]);
6886 }
6887 return strict_points;
6888}
6889
6890// Picks k evenly spaced vertices along a longer cyclic boundary.
6891// O(k).
6892inline std::vector<point<long long>>
6893subsample_boundary(const std::vector<point<long long>> &points, int k) {
6894 int n = static_cast<int>(points.size());
6895 if (n <= k)
6896 return points;
6897
6898 std::vector<point<long long>> sampled_points;
6899 sampled_points.reserve(k);
6900 for (int i = 0; i < k; ++i)
6901 sampled_points.push_back(
6902 points[static_cast<size_t>((static_cast<i128>(i) * n) / k)]);
6903 return sampled_points;
6904}
6905
6906// Random translation so the polygon lies in the box.
6907// O(|points|).
6908inline void place_inside_box(std::vector<point<long long>> &points,
6909 long long min_coord, long long max_coord) {
6910 long long width = max_coord - min_coord + 1;
6911
6912 i128 min_x = points[0].x(), max_x = points[0].x();
6913 i128 min_y = points[0].y(), max_y = points[0].y();
6914 for (const point<long long> &p : points) {
6915 min_x = std::min(min_x, static_cast<i128>(p.x()));
6916 max_x = std::max(max_x, static_cast<i128>(p.x()));
6917 min_y = std::min(min_y, static_cast<i128>(p.y()));
6918 max_y = std::max(max_y, static_cast<i128>(p.y()));
6919 }
6920
6921 i128 span_x = max_x - min_x;
6922 i128 span_y = max_y - min_y;
6923 // Random slack keeps the polygon inside the box without filling it.
6924 i128 shift_x =
6925 min_coord - min_x +
6926 next<long long>(0, width - 1 - static_cast<long long>(span_x));
6927 i128 shift_y =
6928 min_coord - min_y +
6929 next<long long>(0, width - 1 - static_cast<long long>(span_y));
6930
6931 for (point<long long> &p : points)
6932 p = point<long long>(static_cast<long long>(p.x() + shift_x),
6933 static_cast<long long>(p.y() + shift_y));
6934}
6935
6936// Random cyclic shift.
6937// O(|points|).
6938inline void randomize_cyclic_shift(std::vector<point<long long>> &points) {
6939 int rot = next(static_cast<int>(points.size()));
6940 if (rot > 0)
6941 std::rotate(points.begin(), points.begin() + rot, points.end());
6942}
6943
6944// Valtr walk for m edges; bbox minimum translated to the origin.
6945// O(m log m).
6946inline std::vector<point<long long>>
6947valtr_vertices(int m, const std::vector<long long> &x_comp,
6948 std::vector<long long> y_comp) {
6949 shuffle(y_comp.begin(), y_comp.end());
6950
6951 std::vector<point<long long>> edges(m);
6952 // Upper half-plane (positive y, or y = 0 and x > 0) sorts before lower.
6953 auto upper = [](const point<long long> &p) {
6954 return p.y() > 0 or (p.y() == 0 and p.x() > 0);
6955 };
6956 for (int i = 0; i < m; ++i)
6957 edges[i] = point<long long>(x_comp[i], y_comp[i]);
6958
6959 std::sort(edges.begin(), edges.end(),
6960 [&upper](const point<long long> &a, const point<long long> &b) {
6961 bool au = upper(a), bu = upper(b);
6962 if (au != bu)
6963 return au;
6964 auto cross = a ^ b;
6965 if (cross != 0)
6966 return cross > 0;
6967 return (a * a) < (b * b);
6968 });
6969
6970 // Prefix-sum the sorted edge vectors to obtain vertex coordinates.
6971 i128 cur_x = 0, cur_y = 0;
6972 std::vector<i128> px(m), py(m);
6973 for (int i = 0; i < m; ++i) {
6974 px[i] = cur_x;
6975 py[i] = cur_y;
6976 cur_x += edges[i].x();
6977 cur_y += edges[i].y();
6978 }
6979 tgen::detail::tgen_ensure_against_bug(
6980 cur_x == 0 and cur_y == 0,
6981 "geometry: random_convex_polygon: walk did not close");
6982
6983 i128 min_x = px[0], min_y = py[0];
6984 for (int i = 1; i < m; ++i) {
6985 min_x = std::min(min_x, px[i]);
6986 min_y = std::min(min_y, py[i]);
6987 }
6988
6989 // Shift so the bbox minimum is at the origin.
6990 std::vector<point<long long>> points;
6991 points.reserve(m);
6992 for (int i = 0; i < m; ++i)
6993 points.emplace_back(px[i] - min_x, py[i] - min_y);
6994 return points;
6995}
6996
6997} // namespace detail
6998
6999// Generates n vertices of a convex integer polygon inside a box.
7000// If strict is true, boundary vertices are guaranteed non-collinear when
7001// generation succeeds; retry count depends on n and width.
7002// Always returns points in counterclockwise order.
7003// O(n log n).
7004inline std::vector<point<long long>>
7005random_convex_polygon(int n, long long min_coord, long long max_coord,
7006 bool strict = false) {
7007 tgen_ensure(n >= 3,
7008 "geometry: random_convex_polygon: n must be at least 3");
7009 tgen_ensure(max_coord >= min_coord,
7010 "geometry: random_convex_polygon: min_coord must be at most "
7011 "max_coord");
7012 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7013 std::numeric_limits<long long>::max(),
7014 "geometry: random_convex_polygon: coordinate range too large");
7015 long long width = max_coord - min_coord + 1;
7017 width >= n,
7018 "geometry: random_convex_polygon: coordinate range too small for n");
7019
7020 // Valtr walk size: n in weak mode; strict mode uses a larger grid so
7021 // collinear removal still leaves at least n vertices to subsample.
7022 int num_coords = n;
7023 if (strict) {
7024 // Extra grid lines beyond n: at least 100 (small-n headroom), about
7025 // n/1000 for large n, and never more than width - n.
7026 int extra = width <= n ? 0
7027 : static_cast<int>(std::min<long long>(
7028 std::max(100, n / 1000), width - n));
7029 num_coords = n + extra;
7030 }
7031
7032 // Strict mode retries coordinate sampling when simplification leaves < n
7033 // vertices; weak mode has no failure path, so one attempt always suffices.
7034 const int max_attempts = strict ? 32 : 1;
7035 for (int i = 0; i < max_attempts; ++i) {
7036 // Build a convex lattice polygon on [0, width - 1]^2, then translate.
7037 std::vector<long long> x_sorted =
7038 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
7039 std::vector<long long> y_sorted =
7040 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
7041 std::vector<long long> x_comp = detail::valtr_edge_components(x_sorted);
7042 std::vector<long long> y_comp = detail::valtr_edge_components(y_sorted);
7043
7044 std::vector<point<long long>> points =
7045 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
7046
7047 if (strict) {
7048 std::vector<point<long long>> simplified =
7049 detail::simplify_strict_boundary(std::move(points));
7050 // Tight boxes can leave too few vertices -> resample coordinates.
7051 if (static_cast<int>(simplified.size()) < n)
7052 continue;
7053
7054 points = detail::subsample_boundary(simplified, n);
7055 }
7056
7057 detail::place_inside_box(points, min_coord, max_coord);
7058 detail::randomize_cyclic_shift(points);
7059 return points;
7060 }
7061
7062 // Generation failed.
7063 throw tgen::detail::error(
7064 "geometry: random_convex_polygon: generation failed: coordinate "
7065 "range too small for n");
7066}
7067
7068// Random simple polygon through given distinct points.
7069// Collinear triples are allowed; fails if all points are collinear.
7070// Always returns vertices in counterclockwise order.
7071// O(n log n) expected if points are "random", O(n^2) worst case.
7073 const std::vector<point<long long>> &points) {
7074 int n = static_cast<int>(points.size());
7075 tgen_ensure(n >= 3,
7076 "geometry: random_simple_polygon_through_points: need at "
7077 "least 3 points");
7079 static_cast<int>(
7080 std::set<point<long long>>(points.begin(), points.end()).size()) ==
7081 n,
7082 "geometry: random_simple_polygon_through_points: points must "
7083 "be distinct");
7084
7085 int idx_a = 0, idx_b = 0;
7086 for (int i = 1; i < n; ++i) {
7087 if (points[i] < points[idx_a])
7088 idx_a = i;
7089 if (points[idx_b] < points[i])
7090 idx_b = i;
7091 }
7092 point<long long> A = points[idx_a], B = points[idx_b];
7093
7094 bool all_collinear = true;
7095 for (int i = 0; i < n; ++i) {
7096 if (i == idx_a or i == idx_b)
7097 continue;
7098 if (detail::ccw(A, B, points[i]) != 0) {
7099 all_collinear = false;
7100 break;
7101 }
7102 }
7103 tgen_ensure(!all_collinear,
7104 "geometry: random_simple_polygon_through_points: all points "
7105 "are collinear; no simple polygon exists");
7106
7107 // Keep points collinear with AB on the chain that has no other points on
7108 // its side, so AB is split through those vertices instead of crossing them
7109 // later.
7110 int negative_count = 0;
7111 for (int i = 0; i < n; ++i) {
7112 if (i == idx_a or i == idx_b)
7113 continue;
7114 if (detail::ccw(A, B, points[i]) < 0)
7115 ++negative_count;
7116 }
7117
7118 std::vector<point<long long>> chain;
7119 chain.push_back(A);
7120 int left_count = 0;
7121 for (int i = 0; i < n; ++i) {
7122 if (i == idx_a or i == idx_b)
7123 continue;
7124 detail::i128 side = detail::ccw(A, B, points[i]);
7125 if (side < 0 or (side == 0 and negative_count == 0)) {
7126 chain.push_back(points[i]);
7127 ++left_count;
7128 }
7129 }
7130 chain.push_back(B);
7131 for (int i = 0; i < n; ++i) {
7132 if (i == idx_a or i == idx_b)
7133 continue;
7134 detail::i128 side = detail::ccw(A, B, points[i]);
7135 if (side > 0 or (side == 0 and negative_count != 0))
7136 chain.push_back(points[i]);
7137 }
7138 chain.push_back(A);
7139
7140 int n1 = 2 + left_count;
7141 // Upper chain: A -> B.
7142 detail::conquer(chain, 0, n1);
7143 // Lower chain: B -> A.
7144 detail::conquer(chain, n1 - 1, static_cast<int>(chain.size()));
7145
7146 // Cyclic vertex order: chain[1..n1) then chain[n1..end) (skip each path's
7147 // start vertex).
7148 std::vector<point<long long>> poly;
7149 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7150 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7151 return poly;
7152}
7153
7154namespace detail {
7155
7156// Samples n distinct integer points in [min_coord, max_coord]^2.
7157// O(n log n).
7158inline std::vector<point<long long>>
7159random_distinct_points_in_box(int n, long long min_coord, long long max_coord) {
7160 long long width = max_coord - min_coord;
7161 i128 side_128 = width + 1;
7162 i128 universe = side_128 * side_128;
7163 tgen_ensure(universe <= std::numeric_limits<long long>::max(),
7164 "geometry: random_simple_polygon: coordinate range too large");
7165 long long side = static_cast<long long>(side_128);
7166 tgen_ensure(universe >= n,
7167 "geometry: random_simple_polygon: coordinate range too small "
7168 "for n distinct points");
7169
7170 // Decodes a linear grid key (x * side + y) to a point.
7171 auto decode = [&](long long key) -> point<long long> {
7172 return point<long long>(min_coord + key / side, min_coord + key % side);
7173 };
7174
7175 // Repeats until all generated points are not collinear.
7176 // Runs O(1) expected times.
7177 while (true) {
7178 std::vector<long long> keys =
7179 distinct_range<long long>(0, static_cast<long long>(universe - 1))
7180 .gen_list(n)
7181 .to_std();
7182
7183 std::vector<point<long long>> points;
7184 points.reserve(n);
7185 for (long long key : keys)
7186 points.push_back(decode(key));
7187
7188 // Checks if the points are not all collinear.
7189 for (int i = 2; i < n; ++i) {
7190 if (ccw(points[0], points[1], points[i]) != 0)
7191 return points;
7192 }
7193 }
7194}
7195
7196// Axis-aligned edge data for a CCW polygon (interior on the left).
7197// O(1).
7198struct ortho_poly_edge {
7199 long long len;
7200 bool horiz;
7201 long long fixed;
7202 long long lo, hi;
7203 int out_x, out_y;
7204};
7205
7206// True if a, b, c lie on one horizontal or vertical line.
7207// O(1).
7208inline bool ortho_axis_collinear(const point<long long> &a,
7209 const point<long long> &b,
7210 const point<long long> &c) {
7211 return (a.x() == b.x() and b.x() == c.x()) or
7212 (a.y() == b.y() and b.y() == c.y());
7213}
7214
7215// Edge i of poly: orientation, span, exterior normal.
7216// O(1).
7217inline ortho_poly_edge
7218ortho_analyze_edge(const std::vector<point<long long>> &poly, int i) {
7219 int m = static_cast<int>(poly.size());
7220 point<long long> a = poly[i], b = poly[(i + 1) % m];
7221 ortho_poly_edge e{};
7222 if (a.y() == b.y()) {
7223 e.horiz = true;
7224 e.fixed = a.y();
7225 e.lo = std::min(a.x(), b.x());
7226 e.hi = std::max(a.x(), b.x());
7227 e.out_x = 0;
7228 e.out_y = a.x() < b.x() ? -1 : 1;
7229 } else {
7230 e.fixed = a.x();
7231 e.lo = std::min(a.y(), b.y());
7232 e.hi = std::max(a.y(), b.y());
7233 e.out_x = a.y() < b.y() ? 1 : -1;
7234 }
7235 e.len = e.hi - e.lo;
7236 return e;
7237}
7238
7239// True if open axis-aligned segments (a, b) and (c, d) properly cross or
7240// overlap (excluding shared endpoints).
7241// O(1).
7242inline bool ortho_open_seg_cross(const point<long long> &a,
7243 const point<long long> &b,
7244 const point<long long> &c,
7245 const point<long long> &d) {
7246 if (a.y() == b.y() and c.y() == d.y()) {
7247 if (a.y() != c.y())
7248 return false;
7249 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7250 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7251 return lo1 < hi2 and lo2 < hi1;
7252 }
7253 if (a.x() == b.x() and c.x() == d.x()) {
7254 if (a.x() != c.x())
7255 return false;
7256 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7257 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7258 return lo1 < hi2 and lo2 < hi1;
7259 }
7260 if (a.y() == b.y() and c.x() == d.x()) {
7261 long long hx = a.y(), vx = c.x();
7262 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7263 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7264 return hlo < vx and vx < hhi and vlo < hx and hx < vhi;
7265 }
7266 if (a.x() == b.x() and c.y() == d.y()) {
7267 long long vx = a.x(), hy = c.y();
7268 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7269 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7270 return vlo < hy and hy < vhi and hlo < vx and vx < hhi;
7271 }
7272 return false;
7273}
7274
7275// Integral ray-crossing point-in-polygon.
7276// O(|poly|).
7277inline bool ortho_point_inside(const std::vector<point<long long>> &poly,
7278 point<long long> p) {
7279 int m = static_cast<int>(poly.size());
7280 bool inside = false;
7281 for (int i = 0, j = m - 1; i < m; j = i++) {
7282 point<long long> a = poly[i], b = poly[j];
7283 if ((a.y() > p.y()) != (b.y() > p.y())) {
7284 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7285 i128(p.x() - a.x()) * (b.y() - a.y());
7286 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7287 inside = !inside;
7288 }
7289 }
7290 return inside;
7291}
7292
7293// True if p lies strictly in the open segment (a, b).
7294// O(1).
7295inline bool ortho_point_strictly_interior(point<long long> p,
7296 point<long long> a,
7297 point<long long> b) {
7298 if (a.y() == b.y()) {
7299 if (p.y() != a.y())
7300 return false;
7301 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7302 return lo < p.x() and p.x() < hi;
7303 }
7304 if (a.x() == b.x()) {
7305 if (p.x() != a.x())
7306 return false;
7307 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7308 return lo < p.y() and p.y() < hi;
7309 }
7310 return false;
7311}
7312
7313// True if p lies on the closed segment [a, b].
7314// O(1).
7315inline bool ortho_point_on_segment(point<long long> p, point<long long> a,
7316 point<long long> b) {
7317 return p == a or p == b or ortho_point_strictly_interior(p, a, b);
7318}
7319
7320// True if splicing add between A and B on edge_i is valid: no vertex of add
7321// coincides with poly, no boundary self-contact (forward or reverse
7322// T-junctions, collinear overlaps), new segments do not cross other boundary
7323// edges, and inward notches keep all of add inside poly.
7324// O(|poly|), assuming |add| is O(1).
7325inline bool ortho_bump_valid(const std::vector<point<long long>> &poly,
7326 point<long long> A, point<long long> B,
7327 const std::vector<point<long long>> &add,
7328 int edge_i, bool inward) {
7329 int m = static_cast<int>(poly.size());
7330
7331 for (point<long long> v : add)
7332 for (point<long long> q : poly)
7333 if (v == q)
7334 return false;
7335
7336 // Forward T-junction: new vertex on a non-incident edge interior, or on
7337 // edge_i but outside the replaced subsegment [A, B].
7338 for (point<long long> v : add) {
7339 for (int j = 0; j < m; ++j) {
7340 point<long long> c = poly[j], d = poly[(j + 1) % m];
7341 if (j == edge_i) {
7342 if (ortho_point_on_segment(v, c, d) and
7343 !ortho_point_on_segment(v, A, B))
7344 return false;
7345 } else if (ortho_point_strictly_interior(v, c, d)) {
7346 return false;
7347 }
7348 }
7349 }
7350
7351 auto seg_ok = [&](point<long long> s0, point<long long> s1) {
7352 for (int j = 0; j < m; ++j) {
7353 if (j == edge_i)
7354 continue;
7355 point<long long> c = poly[j], d = poly[(j + 1) % m];
7356 if (ortho_open_seg_cross(s0, s1, c, d))
7357 return false;
7358 }
7359 for (int k = 0; k < m; ++k) {
7360 point<long long> q = poly[k];
7361 if (q == s0 or q == s1 or q == A or q == B)
7362 continue;
7363 if (ortho_point_strictly_interior(q, s0, s1))
7364 return false;
7365 }
7366 return true;
7367 };
7368
7369 point<long long> prev = A;
7370 for (point<long long> v : add) {
7371 if (!seg_ok(prev, v))
7372 return false;
7373 prev = v;
7374 }
7375 if (!seg_ok(prev, B))
7376 return false;
7377
7378 if (inward) {
7379 for (point<long long> v : add)
7380 if (!ortho_point_inside(poly, v))
7381 return false;
7382 }
7383
7384 return true;
7385}
7386
7387// Splices a rectangular tab or notch on edge edge_i over [lo, hi], extending
7388// depth units perpendicular to the edge.
7389// O(|poly|).
7390inline bool ortho_bump_edge(std::vector<point<long long>> &poly, int edge_i,
7391 const ortho_poly_edge &e, long long lo,
7392 long long hi, long long depth, bool inward,
7393 size_t max_vertices) {
7394 int m = static_cast<int>(poly.size());
7395 point<long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7396
7397 int step_x = inward ? -e.out_x : e.out_x;
7398 int step_y = inward ? -e.out_y : e.out_y;
7399
7400 std::vector<point<long long>> add;
7401 if (e.horiz) {
7402 long long y = e.fixed, y2 = y + step_y * depth;
7403 if (A.x() < B.x()) {
7404 if (lo > A.x())
7405 add.emplace_back(lo, y);
7406 add.emplace_back(lo, y2);
7407 add.emplace_back(hi, y2);
7408 if (hi < B.x())
7409 add.emplace_back(hi, y);
7410 } else {
7411 if (hi < A.x())
7412 add.emplace_back(hi, y);
7413 add.emplace_back(hi, y2);
7414 add.emplace_back(lo, y2);
7415 if (lo > B.x())
7416 add.emplace_back(lo, y);
7417 }
7418 } else {
7419 long long x = e.fixed, x2 = x + step_x * depth;
7420 if (A.y() < B.y()) {
7421 if (lo > A.y())
7422 add.emplace_back(x, lo);
7423 add.emplace_back(x2, lo);
7424 add.emplace_back(x2, hi);
7425 if (hi < B.y())
7426 add.emplace_back(x, hi);
7427 } else {
7428 if (hi < A.y())
7429 add.emplace_back(x, hi);
7430 add.emplace_back(x2, hi);
7431 add.emplace_back(x2, lo);
7432 if (lo > B.y())
7433 add.emplace_back(x, lo);
7434 }
7435 }
7436 if (poly.size() > max_vertices or add.size() > max_vertices - poly.size())
7437 return false;
7438 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7439 return false;
7440
7441 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7442 return true;
7443}
7444
7445// Picks edge i with probability proportional to
7446// e.len * (4 + min(global_timestamp - last_used[i], 8)).
7447// O(|poly|).
7448inline int ortho_pick_poly_edge(const std::vector<point<long long>> &poly,
7449 std::vector<int> &last_used, int &time_stamp) {
7450 int m = static_cast<int>(poly.size());
7451 if (last_used.size() != static_cast<size_t>(m)) {
7452 last_used.assign(m, 0);
7453 time_stamp = 0;
7454 }
7455 std::vector<long long> weights(m);
7456 long long total = 0;
7457 for (int i = 0; i < m; ++i) {
7458 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7459 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7460 total += weights[i];
7461 }
7462 long long pick = next<long long>(0, total - 1);
7463 for (int i = 0; i < m; ++i) {
7464 pick -= weights[i];
7465 if (pick < 0) {
7466 last_used[i] = ++time_stamp;
7467 return i;
7468 }
7469 }
7470 last_used[m - 1] = ++time_stamp;
7471 return m - 1;
7472}
7473
7474// One random inflate/cut attempt.
7475// O(|poly|).
7476inline bool
7477ortho_try_bump(std::vector<point<long long>> &poly, int n,
7478 std::vector<int> &last_used, int &time_stamp,
7479 bool outward_only = false,
7480 size_t max_vertices = std::numeric_limits<size_t>::max()) {
7481 if (poly.size() < 3)
7482 return false;
7483
7484 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7485 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7486
7487 // Edge subdivision can leave length-1 segments; a tab needs span >= 2.
7488 if (e.len < 2)
7489 return false;
7490
7491 // Random subinterval [lo, lo + span] on the edge, with 2 <= span <= e.len.
7492 long long span = next<long long>(2, e.len);
7493 long long lo = next<long long>(e.lo, e.hi - span);
7494
7495 // max_depth: cap on perpendicular tab/notch height (~sqrt(n), in [2, 12]).
7496 // depth: actual height; shallow usually, up to max_depth 10% of the time.
7497 long long max_depth =
7498 std::clamp(static_cast<long long>(std::sqrt(n) / 2 + 2), 2LL, 12LL);
7499 long long depth =
7500 next(10) == 0 ? next<long long>(std::max(2LL, max_depth / 2), max_depth)
7501 : next<long long>(1, std::max(2LL, max_depth / 3));
7502
7503 bool inward = !outward_only and next(4) == 0;
7504 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward,
7505 max_vertices);
7506}
7507
7508// Drops axis-aligned collinear vertices.
7509// O(n).
7510inline std::vector<point<long long>>
7511ortho_simplify_collinear(std::vector<point<long long>> poly) {
7512 int n = static_cast<int>(poly.size());
7513 if (n < 3)
7514 return poly;
7515 std::vector<point<long long>> out;
7516 out.reserve(n);
7517 for (int i = 0; i < n; ++i) {
7518 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7519 poly[(i + 1) % n]))
7520 out.push_back(poly[i]);
7521 }
7522 return out.size() >= 3 ? out : poly;
7523}
7524
7525// Removes one collinear vertex.
7526// O(n).
7527inline bool ortho_remove_one_collinear(std::vector<point<long long>> &poly) {
7528 int n = static_cast<int>(poly.size());
7529 if (n < 4)
7530 return false;
7531 for (int i = 0; i < n; ++i) {
7532 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7533 poly[(i + 1) % n]))
7534 continue;
7535 poly.erase(poly.begin() + i);
7536 return true;
7537 }
7538 return false;
7539}
7540
7541// Inserts collinear vertices on straight edges until size reaches `target` (or
7542// no edge has spare integer points). Preserves boundary order.
7543// O(target).
7544inline void ortho_fill_collinear(std::vector<point<long long>> &poly,
7545 int target) {
7546 int need = target - static_cast<int>(poly.size());
7547 if (need <= 0)
7548 return;
7549
7550 std::vector<point<long long>> out;
7551 int m = static_cast<int>(poly.size());
7552 out.reserve(poly.size() + need);
7553
7554 for (int i = 0; i < m; ++i) {
7555 point<long long> a = poly[i], b = poly[(i + 1) % m];
7556 out.push_back(a);
7557 if (need <= 0)
7558 continue;
7559
7560 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7561 long long cap = e.len - 1;
7562 if (cap <= 0)
7563 continue;
7564
7565 // Adds `take` collinear vertices to the boundary.
7566 long long take = std::min<long long>(need, cap);
7567 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7568 for (long long k = 0; k < take; ++k) {
7569 long long off = (k + 1) * (cap + 1) / (take + 1);
7570 long long coord = forward ? e.lo + off : e.hi - off;
7571 if (e.horiz)
7572 out.push_back({coord, e.fixed});
7573 else
7574 out.push_back({e.fixed, coord});
7575 }
7576 need -= static_cast<int>(take);
7577 }
7578 poly.swap(out);
7579}
7580
7581// Inserts outward depth-1 corrugation tabs on straight edges until size reaches
7582// `target` (or no edge has room for another tab). Preserves boundary order.
7583// Assumes the scale-up step left every edge on a grid with spacing >= 4.
7584// Each tab perturbs a coordinate by 1 and keeps a >= 2 margin from both
7585// corners, so tabs can only meet tabs on the same or a directly facing edge.
7586// The result is therefore simple and free of collinear triples by construction.
7587// O(target).
7588inline void ortho_fill_corrugation(std::vector<point<long long>> &poly,
7589 size_t target) {
7590 size_t n_sz = poly.size();
7591 if (n_sz >= target)
7592 return;
7593
7594 size_t extra_left = target - n_sz;
7595
7596 std::vector<point<long long>> out;
7597 out.reserve(target);
7598 int n = static_cast<int>(poly.size());
7599
7600 for (int i = 0; i < n; ++i) {
7601 point<long long> a = poly[i], b = poly[(i + 1) % n];
7602 out.push_back(a);
7603
7604 if (extra_left < 4)
7605 continue;
7606
7607 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7608 if (e.len < 5)
7609 continue;
7610
7611 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
7612 long long start = e.horiz ? a.x() : a.y();
7613 long long end = e.horiz ? b.x() : b.y();
7614
7615 for (long long pos = start + 2 * dir;
7616 extra_left >= 4 and (pos - end) * dir <= -3; pos += 2 * dir) {
7617 if (e.horiz) {
7618 long long y2 = e.fixed + e.out_y;
7619 out.push_back({pos, e.fixed});
7620 out.push_back({pos, y2});
7621 out.push_back({pos + dir, y2});
7622 out.push_back({pos + dir, e.fixed});
7623 } else {
7624 long long x2 = e.fixed + e.out_x;
7625 out.push_back({e.fixed, pos});
7626 out.push_back({x2, pos});
7627 out.push_back({x2, pos + dir});
7628 out.push_back({e.fixed, pos + dir});
7629 }
7630 extra_left -= 4;
7631 }
7632 }
7633
7634 poly.swap(out);
7635}
7636
7637// CCW square seed plus boundary inflate/cut to about n vertices.
7638// O(n^2) for n <= 1000; O(n) otherwise.
7639inline std::vector<point<long long>> build_orthogonal_polygon(int n,
7640 bool strict) {
7641 bool scale_up = n > 1000;
7642
7643 long long side = std::max(3LL, static_cast<long long>(std::sqrt(n)));
7644 if (scale_up)
7645 side = std::clamp(static_cast<long long>(2 * std::sqrt(std::sqrt(n))),
7646 8LL, 64LL);
7647 std::vector<point<long long>> poly = {
7648 {0, 0}, {side, 0}, {side, side}, {0, side}};
7649
7650 int target_ops = scale_up ? std::max(1, static_cast<int>(4 * side - 4) / 2)
7651 : std::max(1, (n - 4) / 2);
7652
7653 if (scale_up)
7654 target_ops = std::min(
7655 target_ops,
7656 400 + static_cast<int>(4 * std::sqrt(static_cast<double>(side))));
7657
7658 int failure_limit = std::min(target_ops * 8, 2000);
7659
7660 std::vector<int> last_used;
7661 int time_stamp = 0, consecutive_failures = 0;
7662 size_t max_vertices =
7663 scale_up ? std::numeric_limits<size_t>::max() : static_cast<size_t>(n);
7664 for (int ops = 0; ops < target_ops;) {
7665 if (!scale_up and poly.size() + 2 > static_cast<size_t>(n))
7666 break;
7667
7668 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up,
7669 max_vertices)) {
7670 ++ops;
7671 consecutive_failures = 0;
7672 } else if (++consecutive_failures >= failure_limit) {
7673 break;
7674 }
7675 }
7676 if (strict)
7677 poly = ortho_simplify_collinear(std::move(poly));
7678
7679 if (scale_up) {
7680 while (poly.size() > static_cast<size_t>(n) and
7681 ortho_remove_one_collinear(poly))
7682 ;
7683 long long upscale = std::max(4LL, ((n + 3) / 4 + side - 1) / side);
7684 for (point<long long> &p : poly)
7685 p = {p.x() * upscale, p.y() * upscale};
7686 if (strict)
7687 ortho_fill_corrugation(poly, n);
7688 else
7689 ortho_fill_collinear(poly, n);
7690 } else if (!strict)
7691 ortho_fill_collinear(poly, n);
7692
7693 return poly;
7694}
7695
7696} // namespace detail
7697
7698// Random simple polygon.
7699// If strict, vertex set has no three collinear points
7700// (random_points_general_position); otherwise samples distinct grid points
7701// (collinear triples allowed), so it might be the case that (polygon[i],
7702// polygon[i+1], and polygon[i+2]) are collinear. Polygonizes via
7703// random_simple_polygon_through_points. Always counterclockwise.
7704// O(n log n) expected.
7705inline std::vector<point<long long>>
7706random_simple_polygon(int n, long long min_coord, long long max_coord,
7707 bool strict = false) {
7708 tgen_ensure(n >= 3,
7709 "geometry: random_simple_polygon: n must be at least 3");
7710 tgen_ensure(max_coord >= min_coord,
7711 "geometry: random_simple_polygon: min_coord must be at most "
7712 "max_coord");
7713 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord <=
7714 std::numeric_limits<long long>::max(),
7715 "geometry: random_simple_polygon: coordinate range too large");
7716
7717 std::vector<point<long long>> points =
7718 strict ? random_points_general_position(n, min_coord, max_coord)
7719 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7720 return random_simple_polygon_through_points(points);
7721}
7722
7723// Random orthogonal simple polygon, CCW. Each local bump/scale/fill step
7724// preserves full simplicity, so the result is valid by construction.
7725// Exactly n vertices when !strict; at most n when strict (near n for n > 1000).
7726// O(n^2) for n <= 1000; O(n) otherwise.
7727inline std::vector<point<long long>>
7728random_orthogonal_polygon(int n, long long min_coord, long long max_coord,
7729 bool strict = false) {
7730 tgen_ensure(n >= 4,
7731 "geometry: random_orthogonal_polygon: n must be at least 4");
7732 tgen_ensure(max_coord >= min_coord,
7733 "geometry: random_orthogonal_polygon: min_coord must be at "
7734 "most max_coord");
7735 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7736 std::numeric_limits<long long>::max(),
7737 "geometry: random_orthogonal_polygon: coordinate range too "
7738 "large");
7739 long long width = max_coord - min_coord + 1;
7740 tgen_ensure(width >= 4,
7741 "geometry: random_orthogonal_polygon: coordinate range too "
7742 "small");
7743
7744 long long min_side = std::max(3LL, static_cast<long long>(std::sqrt(n)));
7745 if (n > 1000)
7746 min_side = std::max<long long>(min_side, (n + 3) / 4);
7747 tgen_ensure(min_side < width,
7748 "geometry: random_orthogonal_polygon: coordinate range too "
7749 "small");
7750
7751 for (int attempt = 0; attempt < 8; ++attempt) {
7752 std::vector<point<long long>> poly =
7753 detail::build_orthogonal_polygon(n, strict);
7754
7755 if (!strict and poly.size() != static_cast<size_t>(n))
7756 continue;
7757
7758 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7759 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7760 for (point<long long> p : poly) {
7761 min_x = std::min(min_x, detail::i128(p.x()));
7762 max_x = std::max(max_x, detail::i128(p.x()));
7763 min_y = std::min(min_y, detail::i128(p.y()));
7764 max_y = std::max(max_y, detail::i128(p.y()));
7765 }
7766 if (max_x - min_x >= width or max_y - min_y >= width)
7767 continue;
7768
7769 detail::place_inside_box(poly, min_coord, max_coord);
7770 detail::randomize_cyclic_shift(poly);
7771 return poly;
7772 }
7773
7774 throw tgen::detail::error(
7775 "geometry: random_orthogonal_polygon: generation failed");
7776}
7777
7778} // namespace geometry
7779
7780/************
7781 * *
7782 * HACK *
7783 * *
7784 ************/
7785
7786namespace hack {
7787
7788namespace detail {
7789
7790using namespace tgen::detail;
7791
7792// Computes polynomial hash of a string.
7793// O(|s|).
7794inline int hash_string(const std::string &s, int base, int mod) {
7795 long long h = 0;
7796 for (char c : s)
7797 h = (h * base + c - 'a' + 1) % mod;
7798 return static_cast<int>(h);
7799}
7800
7801// Estimates the length of the string to very likely have a collision.
7802inline int estimate_length(int alphabet_size, int mod) {
7803 // Magic constants.
7804 double base_len = 2.5 * std::log(std::sqrt(mod));
7805 double scale = std::log(alphabet_size) / std::log(2.0);
7806 double adjusted = base_len / std::max(1.0, scale * 0.7);
7807
7808 return static_cast<int>(std::ceil(adjusted));
7809}
7810
7811// Collides two strings to have the same polynomial hash.
7812// O(sqrt(mod) log(mod)) with high probability.
7813inline std::pair<std::string, std::string>
7814birthday_attack(const std::vector<std::string> &alphabet, int base, int mod) {
7815 tgen_ensure(0 < base and base < mod,
7816 "birthday_attack: base must be in (0, mod)");
7817 std::map<uint64_t, std::vector<int>> seen;
7818 int length = estimate_length(static_cast<int>(alphabet.size()), mod);
7819
7820 while (true) {
7821 std::vector<int> seq(length);
7822
7823 std::string s;
7824
7825 for (int i = 0; i < length; ++i) {
7826 seq[i] = next<int>(0, static_cast<int>(alphabet.size()) - 1);
7827 s += alphabet[seq[i]];
7828 }
7829
7830 int h = hash_string(s, base, mod);
7831
7832 auto it = seen.find(h);
7833 if (it != seen.end() and it->second != seq) {
7834 std::string a, b;
7835
7836 for (int x : it->second)
7837 a += alphabet[x];
7838 for (int x : seq)
7839 b += alphabet[x];
7840
7841 if (a != b)
7842 return {a, b};
7843 }
7844
7845 seen[h] = seq;
7846 }
7847}
7848
7849// Tried to find correct multipliers for unordered_map/set to force
7850// collisions. O(1).
7851inline std::set<long long> std_hash_multipliers() {
7852 std::set<long long> multipliers = {85229};
7853
7854 // Codeforces GCC GNU G++17 7.3.0 case.
7855 bool codeforces_gcc_case = true;
7856 if (cpp.version_ != 0 and cpp.version_ != 17)
7857 codeforces_gcc_case = false;
7858 if (compiler.kind_ != compiler_kind::unknown and
7859 compiler.kind_ != compiler_kind::gcc)
7860 codeforces_gcc_case = false;
7861 if (compiler.major_ > 7)
7862 codeforces_gcc_case = false;
7863
7864 if (codeforces_gcc_case)
7865 multipliers.insert(107897);
7866
7867 return multipliers;
7868}
7869
7870} // namespace detail
7871
7872// Fetches prefix of length n of the string "abacabadabacabae...".
7873// O(n).
7874inline std::string abacaba(int n) {
7875 tgen_ensure(n > 0, "str: size must be positive");
7876 std::string str = "a";
7877 char c = 'a';
7878 while (static_cast<int>(str.size()) < n) {
7879 int prev_size = static_cast<int>(str.size());
7880 str += ++c;
7881 for (int j = 0; j < prev_size and static_cast<int>(str.size()) < n; ++j)
7882 str += str[j];
7883 }
7884 return str;
7885}
7886
7887// Two strings that have same polynomial hash for any base, for
7888// mod = power of 2 up to 2^64.
7889// Thue–Morse.
7890// O(1).
7891inline std::pair<std::string, std::string> unsigned_polynomial_hash() {
7892 std::string a, b;
7893 int size = 1 << 10;
7894 for (int i = 0; i < size; ++i) {
7895 a += static_cast<char>('a' + math::detail::popcount(i) % 2);
7896 b += static_cast<char>('a' + ('b' - a[i]));
7897 }
7898 return {a, b};
7899}
7900
7901// Collides two strings to have the same polynomial hash.
7902// O(sqrt(mod) log(mod)) with high probability.
7903// 0 < base < mod.
7904inline std::pair<std::string, std::string> polynomial_hash(int alphabet_size,
7905 int base, int mod) {
7906 tgen_ensure(alphabet_size > 1,
7907 "hack: polynomial_hash: alphabet size must be greater "
7908 "than 1");
7909 tgen_ensure(0 < base and base < mod,
7910 "hack: polynomial_hash: base must be in (0, mod)");
7911
7912 std::vector<std::string> alphabet(alphabet_size);
7913 for (int i = 0; i < alphabet_size; ++i)
7914 alphabet[i] = std::string(1, static_cast<char>('a' + i));
7915 std::iota(alphabet.begin(), alphabet.end(), 'a');
7916 return detail::birthday_attack(alphabet, base, mod);
7917}
7918
7919// Collides two strings to have the same polynomial hash for multiple bases
7920// and mods (up to 2 pairs).
7921// O(sqrt(mod) log^2 (mod)) with high probability,
7922// with mod = max(mod_1, mod_2).
7923inline std::pair<std::string, std::string>
7924polynomial_hash(int alphabet_size, std::vector<int> bases,
7925 std::vector<int> mods) {
7926 tgen_ensure(bases.size() == mods.size(),
7927 "hack: polynomial_hash: bases and mods must have the same "
7928 "size");
7929 tgen_ensure(bases.size() > 0,
7930 "hack: polynomial_hash: must have at least one (base, mod) "
7931 "pair");
7932 tgen_ensure(bases.size() <= 2,
7933 "hack: polynomial_hash: multi-hash hack only supported "
7934 "for up to 2 (base, mod) pairs");
7935
7936 std::vector<std::string> alphabet(alphabet_size);
7937 for (int i = 0; i < alphabet_size; ++i)
7938 alphabet[i] = std::string(1, static_cast<char>('a' + i));
7939 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7940 if (bases.size() == 1)
7941 return {S1, T1};
7942 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7943}
7944
7945// Returns a list of integers for unordered_map/set to force collisions.
7946// O(size).
7947inline std::vector<long long> std_unordered(int size) {
7948 tgen_ensure(size > 0, "hack: std_unordered: size must be positive");
7949 std::set<long long> multipliers = detail::std_hash_multipliers();
7950 long long mult = 1;
7951 std::set<long long>::iterator it = multipliers.begin();
7952
7953 std::vector<long long> list;
7954 while (static_cast<int>(list.size()) < size) {
7955 list.push_back(mult * (*it));
7956 ++it;
7957 if (it == multipliers.end()) {
7958 it = multipliers.begin();
7959 ++mult;
7960 }
7961 }
7962 return list;
7963}
7964
7965// Returns queries that force \Theta(q sqrt n) asymptotic
7966// for Mo algorithm for offline range queries.
7967// Forces \Theta(q sqrt n) pointer moves for any ordering.
7968// O(n log n + q).
7969inline std::vector<std::pair<int, int>> mo_worst_case(int n, int q) {
7970 std::set<std::pair<int, int>> queries;
7971
7972 // Adversarial case.
7973 int sq = static_cast<int>(std::sqrt(n));
7974 for (int i = 0; i < sq; ++i) {
7975 for (int j = i; j < sq; ++j) {
7976 if (i * sq < n and j * sq < n)
7977 queries.emplace(i * sq, j * sq);
7978 }
7979 }
7980
7981 // Push extra queries.
7982 for (int i = 0; i < n; ++i)
7983 if (queries.size() < size_t(q)) {
7984 queries.emplace(0, i);
7985 queries.emplace(i, i);
7986 queries.emplace(i, n - 1);
7987 }
7988
7989 std::vector<std::pair<int, int>> pool(queries.begin(), queries.end());
7990 while (pool.size() < size_t(q)) {
7991 int l = next(0, n - 1);
7992 pool.emplace_back(l, next(l, n - 1));
7993 }
7994
7995 return choose(shuffled(pool), q);
7996}
7997
7998// Returns list of strings that have a high cost to insert in a std::set.
7999// Forces cost \Theta(size log(size)).
8000// Generates: {b, ab, aab, aaab, ...}.
8001// O(size log(size)).
8003 std::vector<std::string> list;
8004 int k = 0, left = size;
8005 while (left > 0) {
8006 int cur_size = std::min(left, k + 1);
8007 left -= cur_size;
8008
8009 char right_char = cur_size == k + 1 ? 'b' : 'c';
8010 list.push_back(std::string(cur_size - 1, 'a') + right_char);
8011
8012 ++k;
8013 }
8014 return tgen::shuffled(list);
8015}
8016
8017// Graph for Dijkstra implementations that relax with <= instead of <.
8018// Unit-weight layered graph: 0 -> {1,2}, then disjoint
8019// 2x2 gadgets (i,i+1) -> {i+2,i+3} for i = 1,3,5,... Many vertices share the
8020// same dist from 0; with `d + w <= dist[j]` each pop re-relaxes the whole
8021// frontier below it. m = 2(n - 2) edges.
8022// O(n).
8025 n >= 3,
8026 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
8027
8028 egraph<int>::value g(n, {}, true);
8029 g.edge_weighted();
8030 g.add_edge(0, 1, 1);
8031 g.add_edge(0, 2, 1);
8032 for (int i = 1; i + 2 < n; i += 2) {
8033 g.add_edge(i, i + 2, 1);
8034 if (i + 3 < n)
8035 g.add_edge(i, i + 3, 1);
8036
8037 g.add_edge(i + 1, i + 2, 1);
8038 if (i + 3 < n)
8039 g.add_edge(i + 1, i + 3, 1);
8040 }
8041
8042 return g.shuffle_except({0});
8043}
8044
8045// Graph for Dijkstra implementations that do not skip stale heap entries
8046// (`if (d > dist[i]) continue`).
8047// Hub mid = n/2: star 0 -> 1..mid-1 (weights 1..mid-1), funnel i -> mid
8048// (weights 1,3,5,...), then mid -> mid+1.. (weight 1).
8049// Without a stale-heap check, mid and its in-neighbors are re-popped and
8050// re-relax.
8051// m = n + mid - 3 edges, mid = floor(n/2).
8052// O(n).
8054 tgen_ensure(n >= 4,
8055 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
8056
8057 int mid = n / 2;
8058 egraph<int>::value g(n, {}, true);
8059 g.edge_weighted();
8060 for (int i = 1; i < mid; ++i)
8061 g.add_edge(0, i, i);
8062 for (int i = 1; i < mid; ++i)
8063 g.add_edge(i, mid, 2 * (mid - i) - 1);
8064 for (int i = mid + 1; i < n; ++i)
8065 g.add_edge(mid, i, 1);
8066
8067 return g.shuffle_except({0});
8068}
8069
8070// Worst-case for FIFO-SPFA.
8071// Forces Omega(n^2) from vertex 0 (Theta(n*m), m = 2n - 3).
8072// Upper chain ai -> a(i+1) weight 1; lower chain bi -> b(i+1) weight 0;
8073// vertical ai -> bi weight 0; cross bi -> a(i+1) weight 1. Upper chain sets
8074// loose dist first; cross edges from settled bi then improve a(i+1).
8075// m = 2n - 3.
8076// O(n).
8077inline egraph<int>::value spfa(int n) {
8078 tgen_ensure(n >= 2, "hack: spfa: n must be at least 2");
8079 tgen_ensure(n % 2 == 0, "hack: spfa: n must be even");
8080
8081 egraph<int>::value g(n, {}, true);
8082 g.edge_weighted();
8083
8084 const int k = n / 2;
8085 for (int i = 0; i + 1 < k; ++i)
8086 g.add_edge(i, i + 1, 1);
8087 for (int i = 0; i + 1 < k; ++i)
8088 g.add_edge(k + i, k + i + 1, 0);
8089 for (int i = 0; i < k; ++i)
8090 g.add_edge(i, k + i, 0);
8091 for (int i = 0; i + 1 < k; ++i)
8092 g.add_edge(k + i, i + 1, 1);
8093
8094 return g.shuffle_except({0});
8095}
8096
8097// Zadeh (1972) anti-shortest-paths flow network for Edmonds-Karp and Dinitz.
8098// Source is vertex 0; sink is vertex 4l + 2k + 1.
8099// n = 4l + 2k + 2, m = 6l + 4k + k^2 - 4.
8100// O(l + k^2).
8101inline egraph<int>::value dinitz_worst_case(int k, int l) {
8102 tgen_ensure(k >= 1, "hack: dinitz_worst_case: k must be at least 1");
8103 tgen_ensure(l >= 1, "hack: dinitz_worst_case: l must be at least 1");
8104
8105 const int p1 = 2 * l - 1;
8106 const int p2 = 2 * l;
8107 const int q1 = 2 * l + 1;
8108 const int q2 = 2 * l + 2;
8109 const int n = 4 * l + 2 * k + 2;
8110
8111 const int flow_cap = k * k * l;
8112 const int layer_cap = k * k;
8113
8114 auto a = [&](int i) { return 2 * l + 3 + 2 * i; };
8115 auto b = [&](int i) { return 2 * l + 4 + 2 * i; };
8116 auto t = [&](int i) { return 4 * l + 2 * k + 1 - i; };
8117
8118 egraph<int>::value g(n, {}, true);
8119 g.edge_weighted();
8120
8121 for (int i = 0; i + 1 < 2 * l - 1; ++i)
8122 g.add_edge(i, i + 1, flow_cap);
8123 for (int i = 0; i + 1 < 2 * l - 1; ++i)
8124 g.add_edge(t(i + 1), t(i), flow_cap);
8125
8126 for (int i = 0; i < 2 * l - 1; i += 2) {
8127 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
8128 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
8129 }
8130
8131 for (int i = 0; i < k; ++i) {
8132 g.add_edge(p1, a(i), flow_cap);
8133 g.add_edge(p2, b(i), flow_cap);
8134 g.add_edge(a(i), q2, flow_cap);
8135 g.add_edge(b(i), q1, flow_cap);
8136 }
8137
8138 for (int i = 0; i < k; ++i)
8139 for (int j = 0; j < k; ++j)
8140 g.add_edge(a(i), b(j), 1);
8141
8142 return g;
8143}
8144
8145// Returns a mask of length 19938, with weights such that xor-ing with mt19937
8146// outputs yields 0.
8147// O(1).
8148template <typename T> std::vector<bool> mt19937_xor_hash() {
8149 static_assert(std::is_same_v<T, int> or std::is_same_v<T, long long>,
8150 "hack: mt19937_xor_hash: T must be int or long long");
8151
8152 constexpr std::size_t deg = 19937;
8153
8154 std::bitset<deg + 1> a, b, c;
8155 b[deg] = c[deg] = 1;
8156 std::size_t l = 0, shift = 1;
8157 std::mt19937 rng32;
8158 std::mt19937_64 rng64;
8159 for (std::size_t n = 0; n < deg * 2; ++n) {
8160 a >>= 1;
8161 if constexpr (std::is_same_v<T, int>)
8162 a[deg] = rng32() & 1;
8163 else
8164 a[deg] = rng64() & 1;
8165
8166 if ((c & a).count() % 2 == 0) {
8167 ++shift;
8168 continue;
8169 }
8170
8171 std::bitset<deg + 1> oc = c;
8172 c ^= (b >> shift);
8173 if (2 * l <= n) {
8174 l = n + 1 - l;
8175 b = oc;
8176 shift = 1;
8177 } else {
8178 ++shift;
8179 }
8180 }
8181
8182 std::vector<bool> mask(deg + 1);
8183 for (std::size_t i = 0; i <= deg; ++i)
8184 mask[i] = c[i];
8185 return mask;
8186}
8187
8188// Convex polygon that breaks naive rotating calipers for maximum vertex
8189// distance (advances j while dist(i, next(j)) > dist(i, j) instead of using
8190// ccw).
8191// O(1).
8192inline std::vector<geometry::point<double>>
8194 return {
8195 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8196 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8197 };
8198}
8199
8200namespace detail {
8201
8202// Builds a hack block of order k (length fib(2k+1)).
8203// O(fib(2k+1)).
8204inline std::vector<int> segment_tree_beats_worst_case_block(int k) {
8205 tgen_ensure(k >= 1,
8206 "hack: segment_tree_beats_worst_case: k must be at least 1");
8207
8208 std::vector<int> a(k + 1), b(k + 1);
8209 std::vector<std::vector<int>> vf(k + 1), vg(k + 1);
8210
8211 a[1] = b[1] = 1;
8212 vf[1] = {1};
8213 vg[1] = {1, 0};
8214
8215 for (int i = 2; i <= k; ++i) {
8216 b[i] = b[i - 1] + a[i - 1];
8217 a[i] = b[i] + a[i - 1];
8218 for (int x : vf[i - 1])
8219 vf[i].push_back(x + a[i] + b[i]);
8220 vf[i].push_back(a[i]);
8221 for (int x : vg[i - 1])
8222 vf[i].push_back(x + a[i]);
8223 vg[i] = vf[i];
8224 vg[i].push_back(0);
8225 for (int x : vg[i - 1])
8226 vg[i].push_back(x);
8227 }
8228
8229 vf[k].push_back(0);
8230 return vf[k];
8231}
8232
8233// Appends one update round for the tiled array (offset (round * an) mod L).
8234// O(fib(2k+1)).
8235inline void
8236segment_tree_beats_append_round(std::vector<std::vector<int>> &updates,
8237 int block_len, int an, int bn, int n,
8238 int round) {
8239 const int off = (round * an) % block_len;
8240 const int add_off = (off + block_len - bn) % block_len;
8241 for (int k = 0; k < block_len; ++k) {
8242 const int s = k * block_len * block_len;
8243 const int sub_end = off + an;
8244 if (sub_end <= block_len)
8245 updates.push_back({1, s + off, s + sub_end, bn});
8246 else {
8247 updates.push_back({1, s + off, s + block_len, bn});
8248 updates.push_back({1, s, s + (sub_end - block_len), bn});
8249 }
8250 const int add_end = add_off + bn;
8251 if (add_end <= block_len)
8252 updates.push_back({0, s + add_off, s + add_end, an});
8253 else {
8254 updates.push_back({0, s + add_off, s + block_len, an});
8255 updates.push_back({0, s, s + (add_end - block_len), an});
8256 }
8257 }
8258 updates.push_back({2, 0, n, an});
8259 for (int k = 0; k < block_len; ++k) {
8260 const int s = k * block_len * block_len;
8261 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8262 }
8263}
8264
8265} // namespace detail
8266
8267// Array and updates for worst case of segment tree beats.
8268// O(fib(2k+1)^3 + q).
8269inline std::pair<std::vector<int>, std::vector<std::vector<int>>>
8270segment_tree_beats_worst_case(int k, int q) {
8271 tgen_ensure(k >= 1,
8272 "hack: segment_tree_beats_worst_case: k must be at least 1");
8273 tgen_ensure(k <= 7, "hack: segment_tree_beats_worst_case: k too large");
8274 tgen_ensure(q > 0,
8275 "hack: segment_tree_beats_worst_case: q must be positive");
8276
8277 const auto &fib = math::fibonacci();
8278 const int block_len = static_cast<int>(fib[k * 2 + 1]);
8279 const int an = static_cast<int>(fib[k * 2]);
8280 const int bn = static_cast<int>(fib[k * 2 - 1]);
8281
8282 const int len = block_len;
8283 const int total = len * len * len;
8284
8285 std::vector<int> block = detail::segment_tree_beats_worst_case_block(k);
8286 std::vector<int> arr(total, 0);
8287 for (int x = 0; x < block_len; ++x) {
8288 const int s = x * len * len;
8289 for (int i = 0; i < block_len; ++i)
8290 arr[s + i] = block[i];
8291 }
8292
8293 std::vector<std::vector<int>> updates;
8294 updates.reserve(q);
8295 const int n = total;
8296 for (int round = 0; updates.size() < static_cast<std::size_t>(q); ++round) {
8297 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8298 round);
8299 if (updates.size() > static_cast<std::size_t>(q))
8300 updates.resize(q);
8301 }
8302 return {arr, updates};
8303}
8304
8305namespace detail {
8306
8307// Near-balanced binary tree in heap layout: parent i, children 2i+1 and 2i+2.
8308// Height Theta(log n).
8309// O(n).
8310inline tree::value binary_heap_tree(int n) {
8311 std::vector<std::pair<int, int>> edges;
8312 for (int i = 0; i < n; ++i) {
8313 if (2 * i + 1 < n)
8314 edges.emplace_back(i, 2 * i + 1);
8315 if (2 * i + 2 < n)
8316 edges.emplace_back(i, 2 * i + 2);
8317 }
8318 return tree::value(n, edges);
8319}
8320
8321// Appends leaves of the heap subtree rooted at `u` in left-to-right order.
8322// O(subtree size).
8323inline void heap_subtree_leaves(int n, int u, std::vector<int> &out) {
8324 if (2 * u + 1 >= n) {
8325 out.push_back(u);
8326 return;
8327 }
8328 heap_subtree_leaves(n, 2 * u + 1, out);
8329 if (2 * u + 2 < n)
8330 heap_subtree_leaves(n, 2 * u + 2, out);
8331}
8332
8333// Path queries between random leaves in the left and right subtrees of the
8334// root. On correct HLD or centroid decomposition each query visits
8335// Theta(log n) chains / centroid-tree nodes.
8336// O(n + q).
8337inline std::vector<std::pair<int, int>> tree_path_worst_queries(int n, int q) {
8338 std::vector<int> left, right;
8339 if (n > 1)
8340 heap_subtree_leaves(n, 1, left);
8341 if (n > 2)
8342 heap_subtree_leaves(n, 2, right);
8343
8344 std::vector<std::pair<int, int>> queries;
8345 for (int i = 0; i < q; ++i)
8346 queries.emplace_back(pick(left), pick(right));
8347 return queries;
8348}
8349
8350// Reverses the lowest `bits` bits of x.
8351// O(bits).
8352inline int reverse_bits(int x, int bits) {
8353 int r = 0;
8354 for (int i = 0; i < bits; ++i) {
8355 r = (r << 1) | (x & 1);
8356 x >>= 1;
8357 }
8358 return r;
8359}
8360
8361// Wilber bit-reversal leaf tour: maximizes left/right preferred-child
8362// alternations on a balanced tree, forcing Theta(q log n) preferred-path
8363// switches in link-cut trees.
8364// O(n log n + q).
8365inline std::vector<int> lct_worst_access(int n, int q) {
8366 int first_leaf = n / 2;
8367 int m = n - first_leaf;
8368
8369 int bits = 0;
8370 while ((1u << bits) < static_cast<unsigned>(m))
8371 ++bits;
8372
8373 std::vector<int> order;
8374 int span = 1 << bits;
8375 for (int i = 0; i < span; ++i) {
8376 int r = reverse_bits(i, bits);
8377 if (r < m)
8378 order.push_back(first_leaf + r);
8379 }
8380
8381 std::vector<int> access;
8382 for (int i = 0; i < q; ++i)
8383 access.push_back(order[i % m]);
8384 return access;
8385}
8386
8387} // namespace detail
8388
8389// Near-balanced tree plus path queries that force Theta(log n) centroid-tree
8390// nodes per query on correct centroid-decomposition implementations.
8391// O(n + q).
8392inline std::pair<tree::value, std::vector<std::pair<int, int>>>
8393centroid_decomposition_worst_case(int n, int q) {
8395 n >= 3,
8396 "hack: centroid_decomposition_worst_case: n must be at least 3");
8398 q >= 1,
8399 "hack: centroid_decomposition_worst_case: q must be at least 1");
8400
8401 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8402}
8403
8404// Near-balanced tree plus path queries that force Theta(log n) heavy-light
8405// chains per query on correct heavy-light decomposition implementations.
8406// O(n + q).
8407inline std::pair<tree::value, std::vector<std::pair<int, int>>>
8408heavy_light_decomposition_worst_case(int n, int q) {
8410 n >= 3,
8411 "hack: heavy_light_decomposition_worst_case: n must be at least "
8412 "3");
8414 q >= 1,
8415 "hack: heavy_light_decomposition_worst_case: q must be at least 1");
8416
8417 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8418}
8419
8420// Near-balanced tree plus a Wilber bit-reversal leaf-access sequence.
8421// O(n log n + q).
8422inline std::pair<tree::value, std::vector<int>>
8423link_cut_tree_worst_case(int n, int q) {
8424 tgen_ensure(n >= 2, "hack: link_cut_tree_worst_case: n must be at least 2");
8425 tgen_ensure(q >= 1, "hack: link_cut_tree_worst_case: q must be at least 1");
8426
8427 return {detail::binary_heap_tree(n), detail::lct_worst_access(n, q)};
8428}
8429
8430} // namespace hack
8431
8432/*********************
8433 * *
8434 * MISCELLANEOUS *
8435 * *
8436 *********************/
8437
8438namespace misc {
8439
8440// Generates a uniformly random balanced parentheses sequence with k '(' and k
8441// ')'. Valid means that for no prefix there are more ')' than '('.
8442// O(size).
8443inline std::string gen_parenthesis(int size) {
8444 tgen_ensure(size > 0 and size % 2 == 0,
8445 "misc: parenthesis: size must be a positive even number");
8446
8447 int k = size / 2;
8448 std::string s;
8449 int open = 0, close = 0;
8450
8451 for (int i = 0; i < size; ++i) {
8452 if (open == k) {
8453 s += ')';
8454 ++close;
8455 continue;
8456 }
8457 if (open == close) {
8458 s += '(';
8459 ++open;
8460 continue;
8461 }
8462
8463 long long a = k - open, b = k - close, h = open - close;
8464
8465 // Probability of placing '(':
8466 // P('(') = (k - open) * (h + 2) / ((k - open + k - close) * (h + 1))
8467 // Derived from ballot numbers ratio.
8468 long long num = a * (h + 2);
8469 long long den = (a + b) * (h + 1);
8470
8471 if (next<long long>(1, den) <= num) {
8472 s += '(';
8473 ++open;
8474 } else {
8475 s += ')';
8476 ++close;
8477 }
8478 }
8479
8480 return s;
8481}
8482
8483} // namespace misc
8484
8485} // namespace tgen
std::vector< int > many_by_distribution(int k, const std::vector< T > &distribution)
Returns many random indices with given probabilities.
Definition tgen.h:934
auto shuffled(const C &container)
Shuffles a container.
Definition tgen.h:963
C::value_type pick(const C &container)
Chooses a random element from container.
Definition tgen.h:992
void shuffle(It first, It last)
Shuffles range inplace, for random_access_iterator.
Definition tgen.h:953
T wnext(T left, T right, int w)
Returns a skewed random number in range.
Definition tgen.h:772
It::value_type pick(It first, It last)
Chooses a random element from an iterator range.
Definition tgen.h:982
T next(T right)
Returns a random number smaller than value.
Definition tgen.h:689
size_t next_by_distribution(const std::vector< T > &distribution)
Returns random index with given probabilities.
Definition tgen.h:922
C::value_type pick_by_distribution(const C &container, std::vector< T > distribution)
Chooses a random element with given probabilities.
Definition tgen.h:1002
#define tgen_ensure(cond,...)
Ensures condition is true.
Definition tgen.h:111
T next(T left, T right)
Returns a random number in range.
Definition tgen.h:710
T wnext(T right, int w)
Returns a skewed random number smaller than value.
Definition tgen.h:747
C choose(const C &container, int k)
Chooses elements from container, as in a subsequence fixed length.
Definition tgen.h:1030
std::vector< point< long long > > random_simple_polygon_through_points(const std::vector< point< long long > > &points)
Generates a random simple polygon through given points.
Definition tgen.h:7072
std::vector< point< long long > > random_points_general_position(int n, long long min_coord, long long max_coord)
Generates random points in general position inside a coordinate box.
Definition tgen.h:6602
std::vector< point< long long > > random_convex_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random convex polygon with given coordinate range.
Definition tgen.h:7005
std::vector< point< long long > > random_simple_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random simple polygon given coordinate range.
Definition tgen.h:7706
std::vector< point< long long > > random_orthogonal_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random orthogonal simple polygon.
Definition tgen.h:7728
wgraph< VWeight, int > vgraph
Vertex-weighted labeled graphs.
Definition tgen.h:6455
graph::value C(int n, bool is_directed=false)
Cycle graph.
Definition tgen.h:6486
wgraph< int, EWeight > egraph
Edge-weighted labeled graphs.
Definition tgen.h:6458
graph::value S(int n)
Star undirected graph.
Definition tgen.h:6510
graph::value K(int n1, int n2)
Complete bipartite undirected graph.
Definition tgen.h:6499
graph::value K(int n)
Complete undirected graph.
Definition tgen.h:6469
wgraph< int, int > graph
Unweighted labeled graphs.
Definition tgen.h:6461
graph::value P(int n, bool is_directed=false)
Path graph.
Definition tgen.h:6475
std::vector< std::pair< int, int > > mo_worst_case(int n, int q)
Query list that forces asymptotic worst-case for Mo's algorithm.
Definition tgen.h:7969
std::vector< bool > mt19937_xor_hash()
Mask that forces a zero XOR hash from std::mt19937 or std::mt19937_64.
Definition tgen.h:8148
egraph< int >::value spfa(int n)
Worst-case for FIFO-SPFA.
Definition tgen.h:8077
egraph< int >::value non_strict_relaxation_dijkstra_bug(int n)
Directed weighted graph for Dijkstra with non-strict relaxation.
Definition tgen.h:8023
std::string abacaba(int n)
Returns the prefix of the infinite word "abacabad...".
Definition tgen.h:7874
std::vector< geometry::point< double > > naive_rotating_calipers_max_dist_bug()
Convex polygon that breaks naive rotating calipers for maximum distance.
Definition tgen.h:8193
std::vector< long long > std_unordered(int size)
List of integers that tries to force collision on std::unordered_set.
Definition tgen.h:7947
std::vector< std::string > string_set_worst_case(int size)
List of strings that have high cost to insert in a std::set.
Definition tgen.h:8002
std::pair< std::string, std::string > unsigned_polynomial_hash()
Returns two strings that force polynomial hash collision for power-of-two mod.
Definition tgen.h:7891
std::pair< std::string, std::string > polynomial_hash(int alphabet_size, int base, int mod)
Returns two strings that force polynomial hash collision given base and mod.
Definition tgen.h:7904
egraph< int >::value dinitz_worst_case(int k, int l)
Flow network for Edmonds-Karp and Dinitz worst-case.
Definition tgen.h:8101
egraph< int >::value stale_heap_dijkstra_bug(int n)
Directed weighted graph for Dijkstra without a stale-heap check.
Definition tgen.h:8053
uint64_t prime_from(uint64_t left)
Computes smallest prime from given value.
Definition tgen.h:2912
uint64_t gen_divisor_count(uint64_t left, uint64_t right, int divisor_count)
Generates random number in range with a given prime number of divisors.
Definition tgen.h:2941
std::vector< int > gen_partition_fixed_size(int n, int k, int part_left=0, std::optional< int > part_right=std::nullopt)
Generates a random partition with fixed size of a number.
Definition tgen.h:3194
uint64_t totient(uint64_t n)
Euler's totient function.
Definition tgen.h:2772
uint64_t congruent_from(uint64_t left, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes smallest congruent from given value.
Definition tgen.h:3013
uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod)
Computes largest congruent up to given value.
Definition tgen.h:3101
uint64_t gen_prime(uint64_t left, uint64_t right)
Generates a random prime in given range.
Definition tgen.h:2887
std::vector< uint64_t > factor(uint64_t n)
Factors a number into primes.
Definition tgen.h:2741
int num_divisors(uint64_t n)
Computes the number of divisors of a given number.
Definition tgen.h:2931
bool is_prime(uint64_t n)
Checks if a number is prime.
Definition tgen.h:2489
std::vector< int > gen_partition(int n, int part_left=1, std::optional< int > part_right=std::nullopt)
Generates a random partition of a number.
Definition tgen.h:3126
constexpr int FFT_MOD
FFT/NTT mod.
Definition tgen.h:3107
uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem, uint64_t mod)
Generates random number in range given a modular congruence.
Definition tgen.h:3003
uint64_t prime_upto(uint64_t right)
Computes largest prime up to given value.
Definition tgen.h:2921
uint64_t highly_composite_upto(uint64_t right)
Largest highly composite number up to given number.
Definition tgen.h:2877
uint64_t congruent_upto(uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes largest congruent up to given value.
Definition tgen.h:3061
std::vector< std::pair< uint64_t, int > > factor_by_prime(uint64_t n)
Factors a number into primes and its powers.
Definition tgen.h:2751
const std::vector< uint64_t > & fibonacci()
Fetches Fibonacci numbers.
Definition tgen.h:3110
uint64_t modular_inverse(uint64_t a, uint64_t mod)
Computes modular inverse.
Definition tgen.h:2766
uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod)
Computes smallest congruent from given value.
Definition tgen.h:3052
const std::vector< uint64_t > & highly_composites()
Fetches highly composite numbers.
Definition tgen.h:2837
std::vector< std::vector< T > > partition_elements(std::vector< T > elements, int k, int min_size=0, std::optional< uint64_t > max_size=std::nullopt)
Partitions a vector into k ordered groups.
Definition tgen.h:3383
std::vector< uint64_t > gen_partition_fixed_size_fast(uint64_t n, int k, uint64_t part_left=0, std::optional< uint64_t > part_right=std::nullopt)
Generates a fast non-uniform partition with fixed size.
Definition tgen.h:3292
uint64_t gen_congruent(uint64_t left, uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Generates random number in range given modular congruences.
Definition tgen.h:2956
std::pair< uint64_t, uint64_t > prime_gap_upto(uint64_t right)
Largest prime gap up to given number.
Definition tgen.h:2818
std::string gen_parenthesis(int size)
Generates a random valid parenthesis sequence.
Definition tgen.h:8443
T opt(const std::string &key, std::optional< T > default_value=std::nullopt)
Gets opt by key.
Definition tgen.h:1491
void set_compiler(compiler_value compiler)
Sets compiler.
Definition tgen.h:1274
T opt(size_t index, std::optional< T > default_value=std::nullopt)
Gets opt by key.
Definition tgen.h:1477
bool has_opt(std::size_t index)
Checks if opt at some index exists.
Definition tgen.h:1459
bool has_opt(const std::string &key)
Checks if opt with some key exists.
Definition tgen.h:1465
void set_cpp_version(int version)
Sets C++ version.
Definition tgen.h:1255
void register_gen(std::optional< long long > seed=std::nullopt)
Sets up the generator without arguments.
Definition tgen.h:1518
void register_gen(int argc, char **argv)
Sets up the generator.
Definition tgen.h:1507
wtree< VWeight, int > vtree
Vertex-weighted labeled trees.
Definition tgen.h:5040
wtree< int, EWeight > etree
Edge-weighted labeled trees.
Definition tgen.h:5043
wtree< int, int > tree
Unweighted labeled trees.
Definition tgen.h:5046
Compiler identity and version.
Definition tgen.h:285
Distinct generator for containers.
Definition tgen.h:1189
auto gen_list(int size)
Generates a list of several distinct elements.
Definition tgen.h:1210
T gen()
Generates a distinct random element from the container.
Definition tgen.h:1206
distinct_container(const C &container)
Creates distinct generator for elements of the given container.
Definition tgen.h:1195
auto gen_all()
Generates all distinct elements left to generate.
Definition tgen.h:1219
size_t size() const
Returns the number of elements left to generate.
Definition tgen.h:1202
Distinct generator for integral ranges.
Definition tgen.h:1052
auto gen_list(int count)
Generates a list of several distinct values.
Definition tgen.h:1092
distinct_range(T left, T right)
Creates distinct generator for values in given range.
Definition tgen.h:1061
auto gen_all()
Generates all distinct values left to generate.
Definition tgen.h:1117
T gen()
Generates a distinct random value in the defined range.
Definition tgen.h:1071
T size() const
Returns the number of values left to generate.
Definition tgen.h:1066
Distinct generator for discrete uniform functions.
Definition tgen.h:323
distinct(Func func, Args... args)
Generates a distinct generator of a discrete uniform function.
Definition tgen.h:329
auto gen_list(int size)
Generates a list of several distinct values.
Definition tgen.h:363
bool empty()
Checks if there is nothing left to generate.
Definition tgen.h:374
auto gen_all()
Generates all distinct values left to generate.
Definition tgen.h:377
auto gen()
Generates a distinct value.
Definition tgen.h:351
Base class for generators (should not be instantiated).
Definition tgen.h:410
auto gen_list(int size, Args &&...args) const
Generates a list of several generation calls.
Definition tgen.h:413
auto gen_until(Pred predicate, int max_tries, Args &&...args) const
Generates a random value from the valid set until a condition is met.
Definition tgen.h:425
auto distinct(Args &&...args) const
Creates distinct generator for current generator.
Definition tgen.h:444
Base class for generator values (should not be instantiated).
Definition tgen.h:467
bool operator<(const Val &rhs) const
Definition tgen.h:470
Point on the plane.
Definition tgen.h:6521
T x() const
x coordinate.
Definition tgen.h:6538
bool operator==(const point &p) const
Coordinate-wise equality.
Definition tgen.h:6561
product_t operator*(const point &p) const
Dot product.
Definition tgen.h:6579
product_t operator^(const point &p) const
Cross product.
Definition tgen.h:6586
point operator*(T c) const
Scalar multiplication.
Definition tgen.h:6576
point operator-(const point &p) const
Vector subtraction.
Definition tgen.h:6571
point(T x=0, T y=0)
Constructs a point.
Definition tgen.h:6535
T y() const
y coordinate.
Definition tgen.h:6541
bool operator<(const point &p) const
Lexicographic order.
Definition tgen.h:6554
point operator+(const point &p) const
Vector addition.
Definition tgen.h:6566
List value.
Definition tgen.h:1686
int size() const
Returns the size of the list value.
Definition tgen.h:1699
value(const std::vector< T > &vec)
Creates a list value from a std::vector.
Definition tgen.h:1695
value & sort()
Sorts the list in non-decreasing order.
Definition tgen.h:1715
auto to_std() const
Converts the list to a std::vector.
Definition tgen.h:1797
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:1729
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:1771
value operator+(const value &rhs) const
Concatenates two lists.
Definition tgen.h:1736
T & operator[](int idx)
Accesses the element at some position of the list.
Definition tgen.h:1702
value & reverse()
Reverses the list.
Definition tgen.h:1722
T pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the list with given probabilities.
Definition tgen.h:1758
value & shuffle()
Shuffles the list in place.
Definition tgen.h:1745
T pick() const
Returns a uniformly random element.
Definition tgen.h:1753
List generator.
Definition tgen.h:1542
list & different(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are different.
Definition tgen.h:1656
list & equal(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are equal.
Definition tgen.h:1609
list & adjacent_different()
Restricts generator s.t. adjacent values are different.
Definition tgen.h:1678
list & all_different()
Restricts generator s.t. all values are different.
Definition tgen.h:1671
list & equal_range(int left, int right)
Restricts generator s.t. all values at index range are equal.
Definition tgen.h:1635
list(int size, std::set< T > values)
Creates list generator defined by value set.
Definition tgen.h:1570
value gen() const
Generates a uniformly random value from the set of valid lists.
Definition tgen.h:1812
list & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:1644
list & different(std::set< int > indices)
Restricts generator s.t. all values in index set are different.
Definition tgen.h:1649
list & different_range(int left, int right)
Restricts generator s.t. all values at index range are different.
Definition tgen.h:1662
list(int size, T value_left, T value_right)
Creates list generator defined by size and range of values.
Definition tgen.h:1562
list & fix(int idx, T val)
Restricts generator s.t. value at index is fixed.
Definition tgen.h:1582
list & equal(std::set< int > indices)
Restricts generator s.t. all values in index set are equal.
Definition tgen.h:1625
Pair value.
Definition tgen.h:4244
T second() const
Returns the second element of a pair value.
Definition tgen.h:4256
value(const T &first, const T &second)
Creates a pair value from first and second values.
Definition tgen.h:4252
value(const std::pair< T, T > &pair)
Creates a pair value from a std::pair.
Definition tgen.h:4251
auto to_std() const
Converts the pair to a std::pair.
Definition tgen.h:4270
T first() const
Returns the first element of a pair value.
Definition tgen.h:4255
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:4259
Pair generator.
Definition tgen.h:4187
value gen() const
Generates a uniformly random value from the set of valid pairs.
Definition tgen.h:4283
pair & neq()
Restricts generator s.t. first is not equal to second.
Definition tgen.h:4214
pair & leq()
Restricts generator s.t. first is less than or equal to second.
Definition tgen.h:4232
pair & lt()
Restricts generator s.t. first is less than second.
Definition tgen.h:4220
pair & gt()
Restricts generator s.t. first is greater than second.
Definition tgen.h:4226
pair(T both_left, T both_right)
Creates pair generator defined by range of values for both first and second.
Definition tgen.h:4204
pair & eq()
Restricts generator s.t. first is equal to second.
Definition tgen.h:4208
pair(T first_left, T first_right, T second_left, T second_right)
Creates pair generator defined by range of values for first and second.
Definition tgen.h:4195
pair & geq()
Restricts generator s.t. first is greater than or equal to second.
Definition tgen.h:4238
Permutation value.
Definition tgen.h:2242
value & print_1_based()
Sets that printed values are 1-based.
Definition tgen.h:2328
std::vector< int > to_std() const
Converts the permutation to a std::vector.
Definition tgen.h:2371
const int & operator[](int idx) const
Returns the image at some position of the permutation.
Definition tgen.h:2271
std::vector< int > to_std_1_based() const
Converts the permutation to a 1-based std::vector.
Definition tgen.h:2375
value & sort()
Sorts the permutation in non-decreasing order.
Definition tgen.h:2295
int parity() const
Parity of the permutation.
Definition tgen.h:2279
int pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the permutation with given probabilities.
Definition tgen.h:2348
int pick() const
Returns a uniformly random element.
Definition tgen.h:2343
value & reverse()
Reverses the permutation.
Definition tgen.h:2303
value(const std::vector< int > &vec)
Creates a permutation value from a std::vector.
Definition tgen.h:2250
int size() const
Returns the size of the permutation value.
Definition tgen.h:2268
value & shuffle()
Shuffles the permutation.
Definition tgen.h:2335
value & inverse()
Inverse of the permutation.
Definition tgen.h:2310
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:2320
Permutation generator.
Definition tgen.h:2210
value gen() const
Generates a uniformly random value from the set of valid permutations.
Definition tgen.h:2385
permutation & cycles(const std::vector< int > &cycle_sizes)
Restricts generator s.t. cycle sizes are fixed.
Definition tgen.h:2229
permutation(int size)
Creates permutation generator defined by size.
Definition tgen.h:2216
permutation & fix(int idx, int val)
Restricts generator s.t. value at index is fixed.
Definition tgen.h:2221
Printer helper for printing containers or sequential generator elements as columns.
Definition tgen.h:616
print_cols(const Args &...args)
Creates a printer object that prints as columns.
Definition tgen.h:619
Printer helper for standard types.
Definition tgen.h:489
print(const T &val, char sep=' ')
Creates a printer object.
Definition tgen.h:492
Printer helper for standard types, printing on a new line.
Definition tgen.h:591
println(const T &val, char sep=' ')
Creates a printer object that prints on a new line.
Definition tgen.h:593
String value.
Definition tgen.h:3849
char pick() const
Returns a uniformly random element.
Definition tgen.h:3923
char pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the string with given probabilities.
Definition tgen.h:3928
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:3941
value & lowercase()
Sets all characters to lowercase.
Definition tgen.h:3891
value & reverse()
Reverses the string.
Definition tgen.h:3884
int size() const
Returns the size of the string value.
Definition tgen.h:3861
value(const std::string &str)
Creates a string value from a std::string.
Definition tgen.h:3856
value & shuffle()
Shuffles the string.
Definition tgen.h:3915
char & operator[](int idx)
Accesses the character at some position of the string.
Definition tgen.h:3864
value & uppercase()
Sets all characters to uppercase.
Definition tgen.h:3900
value operator+(const value &rhs) const
Concatenates two strings.
Definition tgen.h:3909
std::string to_std() const
Converts the string to a std::string.
Definition tgen.h:3962
value & sort()
Sorts the characters in non-decreasing order.
Definition tgen.h:3877
String generator.
Definition tgen.h:3734
str & different(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are different.
Definition tgen.h:3821
str & palindrome(int left, int right)
Restricts generator s.t. range is a palindrome.
Definition tgen.h:3797
value gen() const
Generates a uniformly random value from the set of valid strings.
Definition tgen.h:3968
str(int size, char value_left='a', char value_right='z')
Creates string generator defined by size and range of characters.
Definition tgen.h:3741
str & different(std::set< int > indices)
Restricts generator s.t. all characters in index set are different.
Definition tgen.h:3814
str(const std::string &regex, Args &&...args)
Creates string generator defined by regex.
Definition tgen.h:3754
str & equal(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are equal.
Definition tgen.h:3776
str & equal(std::set< int > indices)
Restricts generator s.t. all characters in index set are equal.
Definition tgen.h:3769
str & equal_range(int left, int right)
Restricts generator s.t. all characters at index range are equal.
Definition tgen.h:3783
str & fix(int idx, char character)
Restricts generator s.t. character at index is fixed.
Definition tgen.h:3762
str & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:3790
str & different_range(int left, int right)
Restricts generator s.t. all characters at index range are different.
Definition tgen.h:3828
str & palindrome()
Restricts generator s.t. string is a palindrome.
Definition tgen.h:3807
str & all_different()
Restricts generator s.t. all characters are different.
Definition tgen.h:3835
str(int size, std::set< char > chars)
Creates string generator defined by character set.
Definition tgen.h:3748
str & adjacent_different()
Restricts generator s.t. adjacent values are different.
Definition tgen.h:3842
Sampler for repeated draws from a fixed weighted distribution.
Definition tgen.h:826
size_t next() const
Generates a random index with probability proportional to the distribution.
Definition tgen.h:909
weighted_sampler(const std::vector< T > &distribution)
Creates a weighted sampler from a probability distribution.
Definition tgen.h:843
Labeled graph value.
Definition tgen.h:5222
value & print_nm()
Prints number of vertices and edges before edge list.
Definition tgen.h:5399
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:5341
value operator!() const
Graph complement of unweighted graph.
Definition tgen.h:5775
std::tuple< int, int, std::vector< std::set< int > > > to_std() const
Converts the graph to std types.
Definition tgen.h:5866
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:5409
int n() const
Number of vertices.
Definition tgen.h:5323
value operator+(const value &rhs) const
Concatenates two graphs (disjoint union).
Definition tgen.h:5809
value & disjoint_union(const value &rhs)
Disjoint union with another graph.
Definition tgen.h:5645
int m() const
Number of edges.
Definition tgen.h:5326
std::tuple< int, int, std::vector< std::set< int > > > to_std_1_based() const
Converts the graph to 1-based std types.
Definition tgen.h:5874
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another graph at given vertex pairs.
Definition tgen.h:5568
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:5346
value(const std::vector< std::set< int > > &adj, bool is_directed=false)
Builds a graph from an adjacency list.
Definition tgen.h:5241
value(int n, const std::vector< std::pair< int, int > > &edges={}, bool is_directed=false)
Builds a graph from number of vertices and edge list.
Definition tgen.h:5262
wgraph< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:5353
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:5332
value & add_vertices(int k, std::optional< std::vector< VWeight > > new_vertex_weights=std::nullopt)
Adds new isolated vertices.
Definition tgen.h:5480
value & print_1_based()
Sets that printed vertex ids are 1-based.
Definition tgen.h:5392
value & random_connected_subgraph(int num_edges)
Random subgraph with a fixed number of edges that keeps components connected.
Definition tgen.h:5684
value(const typename wtree< VWeight, EWeight >::value &t)
Builds an undirected graph from a tree.
Definition tgen.h:5293
value & random_subgraph(int num_edges)
Random subgraph with a fixed number of edges.
Definition tgen.h:5651
value & edge_weighted()
Enables edge-weighted mode on an edgeless graph.
Definition tgen.h:5378
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two graphs by an new edge.
Definition tgen.h:5541
bool is_directed() const
If the graph is directed.
Definition tgen.h:5329
value & add_edge(int u, int v, std::optional< EWeight > w=std::nullopt)
Adds an edge between two vertices.
Definition tgen.h:5507
value & shuffle()
Shuffles all vertices and edge order.
Definition tgen.h:5475
wgraph< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:5367
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:5338
Labeled weighted graph generator.
Definition tgen.h:5186
wgraph(int n, int m, bool is_directed=false, bool has_self_loops=false)
Creates a graph generator for a fixed number of vertices and edges.
Definition tgen.h:5196
static value gen_bipartite(int n1, int n2, int m, bool connected=false)
Generates a random bipartite graph.
Definition tgen.h:6225
value get_connected() const
Random connected undirected graph extending preset edges.
Definition tgen.h:5945
static value gen_np(int n, double p, bool is_directed=false, bool has_self_loops=false)
Generates a random graph where each edge is included independently.
Definition tgen.h:6312
value gen() const
Generates a uniformly random graph satisfying the constraints.
Definition tgen.h:5921
wgraph & add_edge(int u, int v)
Adds a preset edge that must appear in the generated graph.
Definition tgen.h:5204
value get_acyclic() const
Random directed acyclic graph extending preset edges.
Definition tgen.h:6019
static value gen_skewed(int n, int m, int elongation, int spread, bool is_directed=false)
Random skewed connected graph (large diameter).
Definition tgen.h:6122
wgraph & add_edges_from(const value &rhs)
Adds all edges from another graph as preset edges.
Definition tgen.h:5908
Labeled tree value.
Definition tgen.h:4434
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another tree at given vertex pairs.
Definition tgen.h:4738
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:4521
value(int n, const std::vector< std::pair< int, int > > &edges)
Builds a tree from a vertex count and an edge list.
Definition tgen.h:4471
value(const typename wgraph< VWeight, EWeight >::value &g)
Builds a tree from a graph via a Kruskal-like random spanning tree.
Definition tgen.h:6405
value & print_parents(int root=-1)
Prints in parent format instead of edge list.
Definition tgen.h:4592
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:4524
value & edge_weighted()
Enables edge-weighted mode on an edgeless tree.
Definition tgen.h:4562
int n() const
Returns the number of vertices.
Definition tgen.h:4515
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:4604
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:4518
value(const std::vector< std::set< int > > &adj)
Builds a tree from an adjacency list.
Definition tgen.h:4451
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:4529
value & shuffle()
Shuffles vertices and edge order.
Definition tgen.h:4673
std::pair< int, std::vector< std::set< int > > > to_std() const
Converts the tree to a std types.
Definition tgen.h:4901
wtree< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:4536
value & print_n()
Prints the number of vertices before the tree.
Definition tgen.h:4583
std::pair< int, std::vector< std::set< int > > > to_std_1_based() const
Converts the tree to 1-based std types.
Definition tgen.h:4907
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two trees by an edge.
Definition tgen.h:4711
value & print_1_based()
Sets that printed vertex ids are 1-based.
Definition tgen.h:4576
wtree< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:4550
Labeled weighted tree generator.
Definition tgen.h:4407
wtree & add_edge(int u, int v)
Restricts generator s.t. some edge is present.
Definition tgen.h:4419
static value gen_skewed(int n, int elongation)
Random skewed tree (large diameter).
Definition tgen.h:5005
value gen() const
Generates a uniformly random value from the set of valid trees.
Definition tgen.h:4948
wtree(int n)
Creates a tree generator with specified number of vertices.
Definition tgen.h:4413
static value gen_kruskal(int n)
Kruskal-like random labeled tree.
Definition tgen.h:5015