#line 1 "verify/verify-yuki/yuki-0361.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/361"
//
#line 2 "template/template.hpp"
using namespace std ;
// intrinstic
#include <immintrin.h>
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfenv>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <streambuf>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
// utility
#line 3 "template/util.hpp"
namespace Nyaan {
using ll = long long ;
using i64 = long long ;
using u64 = unsigned long long ;
using i128 = __int128_t ;
using u128 = __uint128_t ;
template < typename T >
using V = vector < T > ;
template < typename T >
using VV = vector < vector < T >> ;
using vi = vector < int > ;
using vl = vector < long long > ;
using vd = V < double > ;
using vs = V < string > ;
using vvi = vector < vector < int >> ;
using vvl = vector < vector < long long >> ;
template < typename T >
using minpq = priority_queue < T , vector < T > , greater < T >> ;
template < typename T , typename U >
struct P : pair < T , U > {
template < typename ... Args >
P ( Args ... args ) : pair < T , U > ( args ...) {}
using pair < T , U >:: first ;
using pair < T , U >:: second ;
P & operator += ( const P & r ) {
first += r . first ;
second += r . second ;
return * this ;
}
P & operator -= ( const P & r ) {
first -= r . first ;
second -= r . second ;
return * this ;
}
P & operator *= ( const P & r ) {
first *= r . first ;
second *= r . second ;
return * this ;
}
template < typename S >
P & operator *= ( const S & r ) {
first *= r , second *= r ;
return * this ;
}
P operator + ( const P & r ) const { return P ( * this ) += r ; }
P operator - ( const P & r ) const { return P ( * this ) -= r ; }
P operator * ( const P & r ) const { return P ( * this ) *= r ; }
template < typename S >
P operator * ( const S & r ) const {
return P ( * this ) *= r ;
}
P operator - () const { return P { - first , - second }; }
};
using pl = P < ll , ll > ;
using pi = P < int , int > ;
using vp = V < pl > ;
constexpr int inf = 1001001001 ;
constexpr long long infLL = 4004004004004004004LL ;
template < typename T >
int sz ( const T & t ) {
return t . size ();
}
template < typename T , typename U >
inline bool amin ( T & x , U y ) {
return ( y < x ) ? ( x = y , true ) : false ;
}
template < typename T , typename U >
inline bool amax ( T & x , U y ) {
return ( x < y ) ? ( x = y , true ) : false ;
}
template < typename T >
inline T Max ( const vector < T > & v ) {
return * max_element ( begin ( v ), end ( v ));
}
template < typename T >
inline T Min ( const vector < T > & v ) {
return * min_element ( begin ( v ), end ( v ));
}
template < typename T >
inline long long Sum ( const vector < T > & v ) {
return accumulate ( begin ( v ), end ( v ), 0LL );
}
template < typename T >
int lb ( const vector < T > & v , const T & a ) {
return lower_bound ( begin ( v ), end ( v ), a ) - begin ( v );
}
template < typename T >
int ub ( const vector < T > & v , const T & a ) {
return upper_bound ( begin ( v ), end ( v ), a ) - begin ( v );
}
constexpr long long TEN ( int n ) {
long long ret = 1 , x = 10 ;
for (; n ; x *= x , n >>= 1 ) ret *= ( n & 1 ? x : 1 );
return ret ;
}
template < typename T , typename U >
pair < T , U > mkp ( const T & t , const U & u ) {
return make_pair ( t , u );
}
template < typename T >
vector < T > mkrui ( const vector < T > & v , bool rev = false ) {
vector < T > ret ( v . size () + 1 );
if ( rev ) {
for ( int i = int ( v . size ()) - 1 ; i >= 0 ; i -- ) ret [ i ] = v [ i ] + ret [ i + 1 ];
} else {
for ( int i = 0 ; i < int ( v . size ()); i ++ ) ret [ i + 1 ] = ret [ i ] + v [ i ];
}
return ret ;
};
template < typename T >
vector < T > mkuni ( const vector < T > & v ) {
vector < T > ret ( v );
sort ( ret . begin (), ret . end ());
ret . erase ( unique ( ret . begin (), ret . end ()), ret . end ());
return ret ;
}
template < typename F >
vector < int > mkord ( int N , F f ) {
vector < int > ord ( N );
iota ( begin ( ord ), end ( ord ), 0 );
sort ( begin ( ord ), end ( ord ), f );
return ord ;
}
template < typename T >
vector < int > mkinv ( vector < T > & v ) {
int max_val = * max_element ( begin ( v ), end ( v ));
vector < int > inv ( max_val + 1 , - 1 );
for ( int i = 0 ; i < ( int ) v . size (); i ++ ) inv [ v [ i ]] = i ;
return inv ;
}
vector < int > mkiota ( int n ) {
vector < int > ret ( n );
iota ( begin ( ret ), end ( ret ), 0 );
return ret ;
}
template < typename T >
T mkrev ( const T & v ) {
T w { v };
reverse ( begin ( w ), end ( w ));
return w ;
}
template < typename T >
bool nxp ( T & v ) {
return next_permutation ( begin ( v ), end ( v ));
}
// 返り値の型は入力の T に依存
// i 要素目 : [0, a[i])
template < typename T >
vector < vector < T >> product ( const vector < T > & a ) {
vector < vector < T >> ret ;
vector < T > v ;
auto dfs = [ & ]( auto rc , int i ) -> void {
if ( i == ( int ) a . size ()) {
ret . push_back ( v );
return ;
}
for ( int j = 0 ; j < a [ i ]; j ++ ) v . push_back ( j ), rc ( rc , i + 1 ), v . pop_back ();
};
dfs ( dfs , 0 );
return ret ;
}
// F : void(T&), mod を取る操作
// T : 整数型のときはオーバーフローに注意する
template < typename T , typename F >
T Power ( T a , long long n , const T & I , F && f ) {
static_assert ( std :: is_invocable_r_v < void , F & , T &> ,
"Power callback must be callable as void(T&)" );
T res = I ;
for (; n ; std :: invoke ( f , a = a * a ), n >>= 1 ) {
if ( n & 1 ) std :: invoke ( f , res = res * a );
}
return res ;
}
// T : 整数型のときはオーバーフローに注意する
template < typename T >
T Power ( T a , long long n , const T & I = T { 1 }) {
auto no_op = []( T & ) -> void {};
return Power ( a , n , I , no_op );
}
template < typename T >
T Rev ( const T & v ) {
T res = v ;
reverse ( begin ( res ), end ( res ));
return res ;
}
template < typename T >
vector < T > Transpose ( const vector < T > & v ) {
using U = typename T :: value_type ;
if ( v . empty ()) return {};
int H = v . size (), W = v [ 0 ]. size ();
vector res ( W , T ( H , U {}));
for ( int i = 0 ; i < H ; i ++ ) {
for ( int j = 0 ; j < W ; j ++ ) {
res [ j ][ i ] = v [ i ][ j ];
}
}
return res ;
}
template < typename T >
vector < T > Rotate ( const vector < T > & v , int clockwise = true ) {
using U = typename T :: value_type ;
int H = v . size (), W = v [ 0 ]. size ();
vector res ( W , T ( H , U {}));
for ( int i = 0 ; i < H ; i ++ ) {
for ( int j = 0 ; j < W ; j ++ ) {
if ( clockwise ) {
res [ W - 1 - j ][ i ] = v [ i ][ j ];
} else {
res [ j ][ H - 1 - i ] = v [ i ][ j ];
}
}
}
return res ;
}
} // namespace Nyaan
#line 58 "template/template.hpp"
// bit operation
#line 1 "template/bitop.hpp"
namespace Nyaan {
__attribute__ (( target ( "popcnt" ))) inline int popcnt ( const u64 & a ) {
return __builtin_popcountll ( a );
}
inline int lsb ( const u64 & a ) { return a ? __builtin_ctzll ( a ) : 64 ; }
inline int ctz ( const u64 & a ) { return a ? __builtin_ctzll ( a ) : 64 ; }
inline int msb ( const u64 & a ) { return a ? 63 - __builtin_clzll ( a ) : - 1 ; }
template < typename T >
inline int gbit ( const T & a , int i ) {
return ( a >> i ) & 1 ;
}
template < typename T >
inline void sbit ( T & a , int i , bool b ) {
if ( gbit ( a , i ) != b ) a ^= T ( 1 ) << i ;
}
constexpr long long PW ( int n ) { return 1LL << n ; }
constexpr long long MSK ( int n ) { return ( 1LL << n ) - 1 ; }
} // namespace Nyaan
#line 61 "template/template.hpp"
// inout
#line 1 "template/inout.hpp"
namespace Nyaan {
template < typename T , typename U >
ostream & operator << ( ostream & os , const pair < T , U > & p ) {
os << p . first << " " << p . second ;
return os ;
}
template < typename T , typename U >
istream & operator >> ( istream & is , pair < T , U > & p ) {
is >> p . first >> p . second ;
return is ;
}
template < typename T >
ostream & operator << ( ostream & os , const vector < T > & v ) {
int s = ( int ) v . size ();
for ( int i = 0 ; i < s ; i ++ ) os << ( i ? " " : "" ) << v [ i ];
return os ;
}
template < typename T >
istream & operator >> ( istream & is , vector < T > & v ) {
for ( auto & x : v ) is >> x ;
return is ;
}
istream & operator >> ( istream & is , __int128_t & x ) {
string S ;
is >> S ;
x = 0 ;
int flag = 0 ;
for ( auto & c : S ) {
if ( c == '-' ) {
flag = true ;
continue ;
}
x *= 10 ;
x += c - '0' ;
}
if ( flag ) x = - x ;
return is ;
}
istream & operator >> ( istream & is , __uint128_t & x ) {
string S ;
is >> S ;
x = 0 ;
for ( auto & c : S ) {
x *= 10 ;
x += c - '0' ;
}
return is ;
}
ostream & operator << ( ostream & os , __int128_t x ) {
if ( x == 0 ) return os << 0 ;
if ( x < 0 ) os << '-' , x = - x ;
string S ;
while ( x ) S . push_back ( '0' + x % 10 ), x /= 10 ;
reverse ( begin ( S ), end ( S ));
return os << S ;
}
ostream & operator << ( ostream & os , __uint128_t x ) {
if ( x == 0 ) return os << 0 ;
string S ;
while ( x ) S . push_back ( '0' + x % 10 ), x /= 10 ;
reverse ( begin ( S ), end ( S ));
return os << S ;
}
void in () {}
template < typename T , class ... U >
void in ( T & t , U & ... u ) {
cin >> t ;
in ( u ...);
}
void out () { cout << " \n " ; }
template < typename T , class ... U , char sep = ' ' >
void out ( const T & t , const U & ... u ) {
cout << t ;
if ( sizeof ...( u )) cout << sep ;
out ( u ...);
}
struct IoSetupNya {
IoSetupNya () {
cin . tie ( nullptr );
ios :: sync_with_stdio ( false );
cout << fixed << setprecision ( 15 );
cerr << fixed << setprecision ( 7 );
}
} iosetupnya ;
} // namespace Nyaan
#line 64 "template/template.hpp"
// debug
#line 1 "template/debug.hpp"
namespace DebugImpl {
template < typename U , typename = void >
struct is_specialize : false_type {};
template < typename U >
struct is_specialize <
U , typename conditional < false , typename U :: iterator , void >:: type >
: true_type {};
template < typename U >
struct is_specialize <
U , typename conditional < false , decltype ( U :: first ), void >:: type >
: true_type {};
template < typename U >
struct is_specialize < U , enable_if_t < is_integral < U >:: value , void >> : true_type {
};
void dump ( const char & t ) { cerr << t ; }
void dump ( const string & t ) { cerr << t ; }
void dump ( const bool & t ) { cerr << ( t ? "true" : "false" ); }
void dump ( __int128_t t ) {
if ( t == 0 ) cerr << 0 ;
if ( t < 0 ) cerr << '-' , t = - t ;
string S ;
while ( t ) S . push_back ( '0' + t % 10 ), t /= 10 ;
reverse ( begin ( S ), end ( S ));
cerr << S ;
}
void dump ( __uint128_t t ) {
if ( t == 0 ) cerr << 0 ;
string S ;
while ( t ) S . push_back ( '0' + t % 10 ), t /= 10 ;
reverse ( begin ( S ), end ( S ));
cerr << S ;
}
template < typename U ,
enable_if_t <! is_specialize < U > :: value , nullptr_t > = nullptr >
void dump ( const U & t ) {
cerr << t ;
}
template < typename T >
void dump ( const T & t , enable_if_t < is_integral < T >:: value >* = nullptr ) {
string res ;
if ( t == Nyaan :: inf ) res = "inf" ;
if constexpr ( is_signed < T >:: value ) {
if ( t == - Nyaan :: inf ) res = "-inf" ;
}
if constexpr ( sizeof ( T ) == 8 ) {
if ( t == Nyaan :: infLL ) res = "inf" ;
if constexpr ( is_signed < T >:: value ) {
if ( t == - Nyaan :: infLL ) res = "-inf" ;
}
}
if ( res . empty ()) res = to_string ( t );
cerr << res ;
}
template < typename T , typename U >
void dump ( const pair < T , U >& );
template < typename T >
void dump ( const pair < T * , int >& );
template < typename T >
void dump ( const T & t ,
enable_if_t <! is_void < typename T :: iterator >:: value >* = nullptr ) {
cerr << "[ " ;
for ( auto it = t . begin (); it != t . end ();) {
dump ( * it );
cerr << ( ++ it == t . end () ? "" : ", " );
}
cerr << " ]" ;
}
template < typename T , typename U >
void dump ( const pair < T , U >& t ) {
cerr << "( " ;
dump ( t . first );
cerr << ", " ;
dump ( t . second );
cerr << " )" ;
}
template < typename T >
void dump ( const pair < T * , int >& t ) {
cerr << "[ " ;
for ( int i = 0 ; i < t . second ; i ++ ) {
dump ( t . first [ i ]);
cerr << ( i == t . second - 1 ? "" : ", " );
}
cerr << " ]" ;
}
void trace () { cerr << endl ; }
template < typename Head , typename ... Tail >
void trace ( Head && head , Tail && ... tail ) {
cerr << " " ;
dump ( head );
if ( sizeof ...( tail ) != 0 ) cerr << "," ;
trace ( std :: forward < Tail > ( tail )...);
}
} // namespace DebugImpl
#ifdef NyaanDebug
#define trc(...) \
do { \
cerr << "## " << #__VA_ARGS__ << " = "; \
DebugImpl::trace(__VA_ARGS__); \
} while (0)
#else
#define trc(...) (void(0))
#endif
#ifdef NyaanLocal
#define trc2(...) \
do { \
cerr << "## " << #__VA_ARGS__ << " = "; \
DebugImpl::trace(__VA_ARGS__); \
} while (0)
#else
#define trc2(...) (void(0))
#endif
#line 67 "template/template.hpp"
// macro
#line 1 "template/macro.hpp"
#define each(x, v) for (auto&& x : v)
#define each2(x, y, v) for (auto&& [x, y] : v)
#define all(v) (v).begin(), (v).end()
#define rep(i, N) for (long long i = 0; i < (long long)(N); i++)
#define repr(i, N) for (long long i = (long long)(N)-1; i >= 0; i--)
#define rep1(i, N) for (long long i = 1; i <= (long long)(N); i++)
#define repr1(i, N) for (long long i = (N); (long long)(i) > 0; i--)
#define reg(i, a, b) for (long long i = (a); i < (b); i++)
#define regr(i, a, b) for (long long i = (b)-1; i >= (a); i--)
#define fi first
#define se second
#define ini(...) \
int __VA_ARGS__; \
in(__VA_ARGS__)
#define inl(...) \
long long __VA_ARGS__; \
in(__VA_ARGS__)
#define ins(...) \
string __VA_ARGS__; \
in(__VA_ARGS__)
#define in2(s, t) \
for (int i = 0; i < (int)s.size(); i++) { \
in(s[i], t[i]); \
}
#define in3(s, t, u) \
for (int i = 0; i < (int)s.size(); i++) { \
in(s[i], t[i], u[i]); \
}
#define in4(s, t, u, v) \
for (int i = 0; i < (int)s.size(); i++) { \
in(s[i], t[i], u[i], v[i]); \
}
#define die(...) \
do { \
Nyaan::out(__VA_ARGS__); \
return; \
} while (0)
#line 70 "template/template.hpp"
namespace Nyaan {
void solve ();
}
int main () { Nyaan :: solve (); }
#line 4 "verify/verify-yuki/yuki-0361.test.cpp"
//
#line 2 "game/impartial-game.hpp"
#line 11 "game/impartial-game.hpp"
using namespace std ;
#line 2 "internal/internal-function.hpp"
#line 8 "internal/internal-function.hpp"
namespace nyaan_internal {
template < class >
class function_ref ;
template < class R , class ... Args >
class function_ref < R ( Args ...) > {
void * obj_ = nullptr ;
R ( * call_obj_ )( void * , Args ...) = nullptr ;
R ( * func_ )( Args ...) = nullptr ;
public:
function_ref () noexcept = default ;
function_ref ( std :: nullptr_t ) noexcept {}
function_ref ( R ( * f )( Args ...)) noexcept : func_ ( f ) {}
template <
class F , class Fn = std :: remove_reference_t < F >,
class = std :: enable_if_t <
std :: is_lvalue_reference_v < F &&> &&
! std :: is_same_v < std :: decay_t < F > , function_ref > &&
! std :: is_pointer_v < std :: decay_t < F >> && ! std :: is_function_v < Fn > &&
std :: is_invocable_r_v < R , Fn & , Args ... >>>
function_ref ( F && f ) noexcept {
obj_ = const_cast < void *> ( static_cast < const void *> ( std :: addressof ( f )));
call_obj_ = []( void * p , Args ... args ) -> R {
return std :: invoke ( * static_cast < Fn *> ( p ), std :: forward < Args > ( args )...);
};
}
R operator ()( Args ... args ) const {
if ( call_obj_ ) {
return call_obj_ ( obj_ , std :: forward < Args > ( args )...);
}
if ( ! func_ ) throw std :: bad_function_call ();
return func_ ( std :: forward < Args > ( args )...);
}
explicit operator bool () const noexcept {
return call_obj_ != nullptr || func_ != nullptr ;
}
};
template < class , std :: size_t Capacity = 32 ,
std :: size_t Align = alignof ( std :: max_align_t )>
class inplace_function ;
template < class R , class ... Args , std :: size_t Capacity , std :: size_t Align >
class inplace_function < R ( Args ...), Capacity , Align > {
using storage_t = typename std :: aligned_storage < Capacity , Align >:: type ;
storage_t storage_ ;
R ( * invoke_ )( void * , Args && ...) = nullptr ;
void ( * copy_ )( void * , const void * ) = nullptr ;
void ( * move_ )( void * , void * ) = nullptr ;
void ( * destroy_ )( void * ) = nullptr ;
template < class F >
static R invoke_impl ( void * p , Args && ... args ) {
return std :: invoke ( * static_cast < F *> ( p ), std :: forward < Args > ( args )...);
}
template < class F >
static void copy_impl ( void * dst , const void * src ) {
new ( dst ) F ( * static_cast < const F *> ( src ));
}
template < class F >
static void move_impl ( void * dst , void * src ) {
if constexpr ( std :: is_move_constructible_v < F > ) {
new ( dst ) F ( std :: move ( * static_cast < F *> ( src )));
} else {
new ( dst ) F ( * static_cast < F *> ( src ));
}
}
template < class F >
static void destroy_impl ( void * p ) {
static_cast < F *> ( p ) ->~ F ();
}
template < class F >
void emplace ( F && f ) {
using Fn = std :: decay_t < F > ;
static_assert ( std :: is_invocable_r_v < R , Fn & , Args ... > ,
"inplace_function target is not invocable with this signature" );
static_assert ( sizeof ( Fn ) <= Capacity ,
"inplace_function target is too large; increase Capacity" );
static_assert ( alignof ( Fn ) <= Align ,
"inplace_function target alignment is too strict; increase Align" );
static_assert ( std :: is_copy_constructible_v < Fn > ,
"inplace_function target must be copy constructible" );
if constexpr ( std :: is_pointer_v < Fn > ) {
if ( f == nullptr ) return ;
}
if constexpr ( std :: is_move_constructible_v < Fn > ||
std :: is_lvalue_reference_v < F > ) {
new ( & storage_ ) Fn ( std :: forward < F > ( f ));
} else {
new ( & storage_ ) Fn ( f );
}
invoke_ = & invoke_impl < Fn > ;
copy_ = & copy_impl < Fn > ;
move_ = & move_impl < Fn > ;
destroy_ = & destroy_impl < Fn > ;
}
public:
inplace_function () noexcept = default ;
inplace_function ( std :: nullptr_t ) noexcept {}
~ inplace_function () { reset (); }
inplace_function ( const inplace_function & other ) {
if ( other ) {
other . copy_ ( & storage_ , & other . storage_ );
invoke_ = other . invoke_ ;
copy_ = other . copy_ ;
move_ = other . move_ ;
destroy_ = other . destroy_ ;
}
}
inplace_function ( inplace_function && other ) {
if ( other ) {
other . move_ ( & storage_ , & other . storage_ );
invoke_ = other . invoke_ ;
copy_ = other . copy_ ;
move_ = other . move_ ;
destroy_ = other . destroy_ ;
other . reset ();
}
}
template <
class F , class Fn = std :: decay_t < F >,
class = std :: enable_if_t <! std :: is_same_v < Fn , inplace_function > &&
! std :: is_same_v < Fn , std :: nullptr_t >>>
inplace_function ( F && f ) {
emplace ( std :: forward < F > ( f ));
}
inplace_function & operator = ( const inplace_function & other ) {
if ( this == & other ) return * this ;
reset ();
if ( other ) {
other . copy_ ( & storage_ , & other . storage_ );
invoke_ = other . invoke_ ;
copy_ = other . copy_ ;
move_ = other . move_ ;
destroy_ = other . destroy_ ;
}
return * this ;
}
inplace_function & operator = ( inplace_function && other ) {
if ( this == & other ) return * this ;
reset ();
if ( other ) {
other . move_ ( & storage_ , & other . storage_ );
invoke_ = other . invoke_ ;
copy_ = other . copy_ ;
move_ = other . move_ ;
destroy_ = other . destroy_ ;
other . reset ();
}
return * this ;
}
template <
class F , class Fn = std :: decay_t < F >,
class = std :: enable_if_t <! std :: is_same_v < Fn , inplace_function > &&
! std :: is_same_v < Fn , std :: nullptr_t >>>
inplace_function & operator = ( F && f ) {
reset ();
emplace ( std :: forward < F > ( f ));
return * this ;
}
inplace_function & operator = ( std :: nullptr_t ) noexcept {
reset ();
return * this ;
}
void reset () noexcept {
if ( destroy_ ) destroy_ ( & storage_ );
invoke_ = nullptr ;
copy_ = nullptr ;
move_ = nullptr ;
destroy_ = nullptr ;
}
explicit operator bool () const noexcept { return invoke_ != nullptr ; }
R operator ()( Args ... args ) const {
if ( ! invoke_ ) throw std :: bad_function_call ();
return invoke_ (
const_cast < void *> ( static_cast < const void *> ( & storage_ )),
std :: forward < Args > ( args )...);
}
};
} // namespace nyaan_internal
using nyaan_internal :: function_ref ;
using nyaan_internal :: inplace_function ;
#line 14 "game/impartial-game.hpp"
/**
* ゲームの遷移が DAG で表せる不偏ゲームの solver
*
* Board:盤面の型
* Move は着手の型 or void
* Game は
*
* - splittable = true の場合は vector<Board> (ゲームの分割に対応)
* - splittable = falseの場合は Board
*
* State は次
*
* - Move が void である場合, Game
* - Move が void でない場合, pair<Game, Move>
*
* States は vector<State>
*
* F は Board を引数, States を返り値に取る callable。つまり
*
* - デフォルトの場合 : vector<Board>(Board)
* - splittable の場合 : vector<vector<Board>>(Board)
* - Move != void の場合は返り値の value_type が pair(*, move) になる
*
* 雑にゲームの勝敗を知りたいときはデフォルトでよい
* 最善手の情報が欲しいときは Move の引数を変えて頑張る
*/
template < typename Board , typename Move = void , bool splittable = false >
struct ImpartialGameSolver {
using Boards = vector < Board > ;
using Game = conditional_t < splittable , vector < Board > , Board > ;
using State = conditional_t < is_void_v < Move > , Game , pair < Game , Move >> ;
using States = vector < State > ;
using Nimber = long long ;
using F = nyaan_internal :: inplace_function < States ( Board ), 64 > ;
map < Board , Nimber > mp ;
F f ;
ImpartialGameSolver () = default ;
ImpartialGameSolver ( const F & _f ) : f ( _f ) {}
template < typename Func ,
typename = enable_if_t < is_invocable_r_v < States , Func & , Board > >>
ImpartialGameSolver ( Func && _f ) : f ( std :: forward < Func > ( _f )) {}
void set_func ( const F & _f ) { f = _f ; }
template < typename Func >
auto set_func ( Func && _f )
-> enable_if_t < is_invocable_r_v < States , Func & , Board > , void > {
f = std :: forward < Func > ( _f );
}
template < typename T >
Nimber get ( const T & t ) {
if constexpr ( is_same_v < T , Board > ) {
if ( mp . count ( t )) return mp [ t ];
return mp [ t ] = _get ( t );
} else if constexpr ( is_same_v < T , Boards > ) {
Nimber n = 0 ;
for ( const Board & s : t ) n ^= get ( s );
return n ;
} else {
static_assert ( is_same_v < T , pair < Game , Move >> );
return get ( t . first );
}
}
// 負け局面で呼ぶと RE する
template < typename T >
conditional_t < is_same_v < T , Board > , Move , pair < int , Move >> get_best_move (
const T & t ) {
static_assert ( is_void_v < Move > == false );
Nimber n = get ( t );
assert ( n != 0 and "No Best Move." );
if constexpr ( is_same_v < T , Board > ) {
auto res = change_x ( t , n );
if ( res . first ) return res . second ;
} else {
static_assert ( is_same_v < T , Boards > );
for ( int i = 0 ; i < ( int ) t . size (); i ++ ) {
auto res = change_x ( t [ i ], n );
if ( res . first ) return { i , res . second };
}
}
assert ( false and "Error in get_best_move()." );
exit ( 1 );
}
private:
Nimber _get ( const Board & b ) {
States gs = std :: invoke ( f , b );
if ( gs . empty ()) return {};
vector < Nimber > ns ;
for ( State & st : gs ) ns . push_back ( get ( st ));
sort ( begin ( ns ), end ( ns ));
ns . erase ( unique ( begin ( ns ), end ( ns )), end ( ns ));
for ( int i = 0 ; i < ( int ) ns . size (); i ++ ) {
if ( ns [ i ] != i ) return i ;
}
return ns . size ();
}
// nimber が x 変わるような着手を返す
pair < bool , Move > change_x ( const Board & b , Nimber x ) {
assert ( is_void_v < Move > == false );
Nimber n = get ( b );
for ( auto & st : std :: invoke ( f , b )) {
if ( get ( st ) == ( x ^ n )) return { true , st . second };
}
return { false , Move {}};
}
};
/**
* @brief 不偏ゲーム
*/
#line 6 "verify/verify-yuki/yuki-0361.test.cpp"
using namespace Nyaan ;
void q () {
ini ( L , D );
auto f = [ & ]( int x ) -> vvi {
vvi res ;
for ( int a = 1 ; a <= x ; a ++ ) {
int bs = a + 1 ;
int be = x - a ;
for ( int b = bs ; b <= be ; b ++ ) {
int c = x - a - b ;
if ( b < c and c <= a + D ) {
res . push_back ( vi { a , b , c });
}
}
}
return res ;
};
ImpartialGameSolver < int , void , true > game ( f );
out ( game . get ( L ) ? "kado" : "matsu" );
}
void Nyaan :: solve () {
int t = 1 ;
// in(t);
while ( t -- ) q ();
}