#ifndef INCLUDE_MODE #define INCLUDE_MODE // #define REACTIVE // #define USE_GETLINE /* #define SUBMIT_ONLY */ #define DEBUG_OUTPUT // #define SAMPLE_CHECK dummy #endif #ifdef INCLUDE_MAIN class SimulatedAnnealing { public: // constexpr data static constexpr double log_temparature_min = 1e-2; static constexpr int updatability_scale = 1e5; static constexpr double log_updatability_scale = log( updatability_scale ); // 山登りを行わない場合はtime_threshold0を-1にする。 static constexpr double time_threshold0 = -1; static constexpr double time_threshold1 = 1800; static constexpr double time_threshold2 = 2200; // mode int mode; // 現在どの最適化を進めている段階か。mode==0の時は山登りを行う。 int mode_temp; // mode確認用の変数。 double start_time; // Execute開始時刻。 // stable parameter int N; int K; int sx; int sy; int tx; int ty; // temporary/optimal parameter vector S,S_opt; int black,black_opt; // 近傍探索用memory (先頭にmをつけて衝突を避ける) // ComputeScore()に計算コストがかかる場合は差分計算用の変数もここに用意する。 // int mi; // int mj; vector mi; vector mj; // score using score_type = ll; // 変えても良いが、変える場合はUpdatable判定も変更が必要。 score_type score,score_opt,score_local_opt; SimulatedAnnealing( const int& N , const int& K , const int& sx , const int& sy , const int& tx , const int& ty ) : N( N ) , K( K ) , sx( sx ) , sy( sy ) , tx( tx ) , ty( ty ) { mode = 0; // temporary parameterの初期化 S = grid; black = 0; // 近傍探索用memoryの初期化 // mi = 0; // mj = 0; // 単発の貪欲法など、繰り返しをともなわない前処理を以下に行う。 // VVV FOR( i , 0 , H ){ FOR( j , 0 , W ){ S[i][j] = ".#"[GetRand(0,1)]; } } // AAA SetOptimal(); } void SetOptimal() { S_opt = S; black_opt = black; } void OptimiseTemporary() { // 必要な部分のみ変更してもよい。 S = S_opt; black = black_opt; } // 近傍探索用memoryの変更。 // small testのインクリメント、random testの乱択に相当。 void Increment0( const double& current_time ) { // mode==0は山登り用。山登りが不要ならば実装は空で良い。 // double rate = time_threshold0 - 0.001 < start_time ? 1.0 : ( current_time - start_time ) / ( time_threshold0 - start_time ); // if( ++mj == H ){ // mj = 0; // if( ++mi == W ){ // mi = 0; // } // } // if( ( mi == sx && mj == sy ) || ( mi == tx && mj == ty ) ){ // Increment0( current_time ); // } } // 近傍探索用memoryを用いたtemporary parameterの変更。 void Shift0( const double& current_time ) { Increment0( current_time ); Revert0(); } // 近傍探索用memoryを用いたtemporary parameterの復元。 void Revert0() { // if( S[mi][mj] == '.' ){ // S[mi][mj] = '#'; // black++; // } else { // S[mi][mj] = '.'; // black--; // } int L = len( mi ); FOR( i , 0 , L ){ if( S[mi[i]][mj[i]] == '.' ){ S[mi[i]][mj[i]] = '#'; black++; } else { S[mi[i]][mj[i]] = '.'; black--; } } CERR( S ); } void Increment1( const double& current_time ) { // mode>0から焼き鈍す。 // double rate = time_threshold1 - 0.001 < start_time ? 1.0 : ( current_time - start_time ) / ( time_threshold1 - start_time ); // mi = GetRand( 0 , N - 1 ); // mj = GetRand( 0 , N - 1 ); // if( ( mi == sx && mj == sy ) || ( mi == tx && mj == ty ) ){ // Increment1( current_time ); // } int k = K - score_local_opt / HW; REPEAT( k ){ int i = GetRand( 0 , Hm ); int j = GetRand( 0 , Wm ); while( ( i == sx && j == sy ) || ( i == tx && j == ty ) ){ i = GetRand( 0 , Hm ); j = GetRand( 0 , Wm ); } mi <<= i; mj <<= j; } } void Shift1( const double& current_time ) { Increment1( current_time ); Revert0(); } void Revert1() { Revert0(); } void Increment2( const double& current_time ) { // double rate = time_threshold2 - 0.001 < start_time ? 1.0 : ( current_time - start_time ) / ( time_threshold2 - start_time ); abort(); } void Shift2( const double& current_time ) { Increment2( current_time ); abort(); } void Revert2() { abort(); } void ModeChange() { OptimiseTemporary(); CERR( "" ); CERR( "Changed mode:" , mode , "->" , mode_temp ); CERR( "Current score:" , ComputeScore() ); CERR( "" ); mode = mode_temp; } void Shift( const double& current_time ) { mode_temp = 0; if( mode == mode_temp++ ){ // time_threshold0がfinal_time以上の時はmodeをこれ以上更新しない。 if( current_time > time_threshold0 ){ ModeChange(); } } else if( mode == mode_temp++ ){ if( current_time > time_threshold1 ){ ModeChange(); } } else if( mode == mode_temp++ ){ if( current_time > time_threshold2 ){ ModeChange(); } } else { abort(); } mode_temp = 0; if( mode == mode_temp++ ){ Shift0( current_time ); } else if( mode == mode_temp++ ){ Shift1( current_time ); } else if( mode == mode_temp++ ){ Shift2( current_time ); } else { abort(); } } void Revert() { mode_temp = 0; if( mode == mode_temp++ ){ Revert0(); } else if( mode == mode_temp++ ){ Revert1(); } else if( mode == mode_temp++ ){ Revert2(); } else { abort(); } } // コストではなくスコア。大きいほど良い。 const score_type& ComputeScore() { /* 3次元化 */ int D = 4 , HWD = HW * D; auto EnumHWD = [&]( const int& v ){ auto [i,j] = EnumHW( v / D ); return T3( i , j , v % D ); }; auto EnumHWD_inv = [&]( const T3& ijk ){ auto& [i,j,k] = ijk; return EnumHW_inv( {i,j} ) * D + k; }; auto edge = [&]( const T3& v ){ vector> answer{}; auto& [i,j,k] = v; if( k == 1 ){ answer <<= {i,j,2}; } else if( k == 3 ){ answer <<= {i,j,0}; } else { RUN( EdgeOnGrid( {i,j} ) , [p,q] ){ answer <<= {p,q,S[i][j]==S[p][q]?k:k+1}; } } return answer; }; EnumerationGraph graph{ HWD , EnumHWD , EnumHWD_inv , edge }; using T = T3; BFS bfs{ graph , T{-1,-1,-1} , T{sx,sy,0} }; auto d = bfs.GetDistance(); auto& di = d[EnumHWD_inv({tx,ty,0})]; if( di <= K ){ score = di * HW + black; } else { score = ( K * 2 - di + 1 ) * HW - black; } return score; } // 基本的に変えなくて良い。 double Temparature( const double& log_temparature_min , const double& time , const int& time_lim ) { return exp( ( log_temparature_min * time ) / time_lim ); } // 基本的に変えなくて良い。 bool Updatable( const int& updatability_scale , const score_type& score , const score_type& score_local_opt , const double& log_temparature_min , const double& time , const int& time_lim ) { return score > score_local_opt || ( mode > 0 && GetRand( 0 , updatability_scale ) < exp( ( score - score_local_opt ) / Temparature( log_temparature_min , time , time_lim ) + log_updatability_scale ) ); } // 基本的に最適判定以外は変えなくて良い。 const score_type& Execute( const double& log_temparature_min , const double& executed_time , const double& final_time , const int& updatability_scale ) { START_WATCH; start_time = executed_time; const double time_lim = final_time - start_time; score_opt = ComputeScore(); score_local_opt = score_opt; while( CHECK_WATCH( time_lim ) ){ if( score_opt >= K * HW ){ CERR( "Reached the maximum:" , score_opt ); break; } Shift( current_time ); const score_type score = ComputeScore(); if( Updatable( updatability_scale , score , score_local_opt , log_temparature_min , current_time , time_lim ) ){ if( score > score_opt ){ CERR( "Updated the optimal score:" , score_opt , "->" , score ); SetOptimal(); score_opt = score_local_opt = score; } else { if( score > score_local_opt ){ CERR( "Updated the local optimal score:" , score_local_opt , "->" , score ); } else if( score < score_local_opt ){ CERR( "Changed the local optimal score:" , score_local_opt , "->" , score ); } else { CERR( "Kept the local optimal score:" , score_local_opt ); } score_local_opt = score; } } else { CERR( "Declined the last score:" , score ); Revert(); } } OptimiseTemporary(); #ifdef DEBUG CERR( "The last score is:" , score_opt ); assert( score_opt == ComputeScore() ); #endif return score_opt; } }; VO Solve() { CEXPR( double , log_temparature_min , 1e-2 ); CEXPR( int , updatability_scale , 1e5 ); CIN( int , N , K , sx , sy , tx , ty ); --sx; --sy; --tx; --ty; if( K >= N * 4 ){ RETURN( -1 ); } START_WATCH; // SA.Executeに渡すCURRENT_TIMEに使う。 SET_HW( N , N ); grid = vector( H , string( W , '.' ) ); SimulatedAnnealing SA{ N , K , sx , sy , tx , ty }; CEXPR( int , final_time , 2000 ); auto score = SA.Execute( log_temparature_min , CURRENT_TIME , final_time , updatability_scale ); if( score >= K * HW ){ FOR( i , 0 , N ){ COUT( SA.S[i] ); } } else { COUT( -1 ); } } REPEAT_MAIN(1); #else /* INCLUDE_MAIN */ #ifdef INCLUDE_SUB // /* COMPAREに使用。圧縮時は削除する。*/ // using answer_type = ll; // answer_type Naive( int N , int M , int K , const vector& A , const bool& debug_output = true ) // { // answer_type a{}; // return a; // } // // answer_type Answer( int N , int M , int K , const vector& A , const bool& debug_output = true ) // { // answer_type a{}; // return a; // } /* 圧縮時は中身だけ削除する。*/ IN VO Experiment() { // 1変数 ../Contest/Template/Experiment/OneVariable.txt // 2変数 ../Contest/Template/Experiment/TwoVariable.txt // 3変数 ../Contest/Template/Experiment/ThreeVariable.txt } /* 圧縮時は中身だけ削除する。*/ IN VO SmallTest() { // 数 ../Contest/Template/SmallTest/Number.txt // 配列 ../Contest/Template/SmallTest/Array.txt // 順列 ../Contest/Template/SmallTest/Permutation.txt // 文字列 ../Contest/Template/SmallTest/String.txt // グリッド ../Contest/Template/SmallTest/Grid.txt // グラフ ../Contest/Template/SmallTest/Graph.txt // 重み付きグラフ ../Contest/Template/SmallTest/WeightedGraph.txt // 区間クエリ ../Contest/Template/SmallTest/IntervalQuery.txt CERR( "全てのケースを確認しました。" ); } /* 圧縮時は中身だけ削除する。*/ IN VO RandomTest( const int& test_case_num ) { // 数 ../Contest/Template/RandomTest/Number.txt // 配列 ../Contest/Template/RandomTest/Array.txt // 順列 ../Contest/Template/RandomTest/Permutation.txt // 文字列 ../Contest/Template/RandomTest/String.txt // グリッド ../Contest/Template/RandomTest/Grid.txt // グラフ ../Contest/Template/RandomTest/Graph.txt // 重み付きグラフ ../Contest/Template/RandomTest/WeightedGraph.txt // 区間クエリ ../Contest/Template/RandomTest/IntervalQuery.txt // 多種クエリ ../Contest/Template/RandomTest/MultiTypeQuery.txt REPEAT( test_case_num ){ } CERR( "全てのケースを確認しました。" ); } #define INCLUDE_MAIN #include __FILE__ #else /* INCLUDE_SUB */ #ifdef INCLUDE_LIBRARY /* VVV 常設でないライブラリは以下に挿入する。*/ // AffineSpace ../Contest/Template/Library/AffineSpace.txt // Arithmetic ../Contest/Template/Library/Arithmetic.txt // BFS ../Contest/Template/Library/BFS.txt // BIT ../Contest/Template/Library/BIT.txt // CoordinateCompress ../Contest/Template/Library/CoordinateCompress.txt // DFS ../Contest/Template/Library/DFS.txt // DifferenceSequence ../Contest/Template/Library/DifferenceSequence.txt // Dijkstra ../Contest/Template/Library/Dijkstra.txt // Knapsack ../Contest/Template/Library/Knapsack.txt // Matrix ../Contest/Template/Library/Matrix.txt // Polynomial ../Contest/Template/Library/Polynomial.txt // Set ../Contest/Template/Library/Set.txt // SqrtDecomposition ../Contest/Template/Library/SqrtDecomposition.txt // UnionFind ../Contest/Template/Library/UnionFind.txt #define BFS BreadthFirstSearch #ifdef DEBUG #include "c:/Users/user/Documents/Programming/Mathematics/Geometry/Graph/Algorithm/BreadthFirstSearch/Debug/a_Body.hpp" #else #define VBFS VirtualBreadthFirstSearch TE CL VBFS{PU:GRAPH& m_G;T m_external;bool m_initialised;LI> m_next;VE m_reached;VE m_prev;IN VBFS(GRAPH& G,CO T& external);TE IN VBFS(GRAPH& G,CO T& external,Arg&& init);IN VO Initialise();IN VO Initialise(T init);TE TY VEC> IN VO Initialise(VEC inits);IN VO Shift(T init);TE TY VEC> IN VO Shift(VEC inits);IN CRI SZ()CO NE;IN VE::reference reached(CO T& t);IN CO T& prev(CO T& t);IN T Next();tuple,VE>,int> GetConnectedComponent();VE GetNodeEnumeration();VE GetReversedNodeEnumeration();VI VO Push(LI>& next,CO T& t,CO T& p)= 0;}; TE IN VBFS::VBFS(GRAPH& G,CO T& external):m_G(G),m_external(external),m_initialised(false),m_next(),m_reached(),m_prev(){ST_AS(is_same_v,T>);}TE TE IN VBFS::VBFS(GRAPH& G,CO T& external,Arg&& init):VBFS(G,external){Initialise(forward(init));}TE IN VO VBFS::Initialise(){m_initialised = true;CRI V = SZ();m_next.clear();m_reached = VE(V);m_prev = VE(V,m_external);}TE IN VO VBFS::Initialise(T init){Initialise();m_next <<={MO(init),m_external};}TE TE TY VEC> IN VO VBFS::Initialise(VEC inits){Initialise();for(auto& init:inits){m_next <<={MO(init),m_external};}}TE IN VO VBFS::Shift(T init){if(m_initialised){m_next ={{MO(init),m_external}};}else{Initialise(MO(init));}}TE TE TY VEC> IN VO VBFS::Shift(VEC inits){if(m_initialised){m_next.clear();for(auto& init:inits){m_next <<={MO(init),m_external};}}else{Initialise(MO(inits));}}TE IN CRI VBFS::SZ()CO NE{RE m_G.SZ();}TE IN VE::reference VBFS::reached(CO T& t){auto&& i = m_G.Enumeration_inv(t);if(!m_initialised){Initialise();}RE m_reached[i];}TE IN CO T& VBFS::prev(CO T& t){auto&& i = m_G.Enumeration_inv(t);if(!m_initialised){Initialise();}RE m_prev[i];}TE IN T VBFS::Next(){if(m_next.empty()){RE m_external;}auto[t_curr,p]= m_next.front();m_next.pop_front();auto&& i = m_G.Enumeration_inv(t_curr);if(m_reached[i]){RE Next();}m_reached[i]= true;m_prev[i]= p;for(auto& t:m_G.Edge(t_curr)){Push(m_next,m_G.Vertex(t),t_curr);}RE t_curr;}TE tuple,VE>,int> VBFS::GetConnectedComponent(){ST_AS(!is_same_v>);CRI V = SZ();VE cc_num(V,-1);VE> cc_num_inv{};int count = 0;for(int i = 0;i < V;i++){if(cc_num[i]== -1){Shift(m_G.Enumeration(i));T t = Next();if(t != m_external){cc_num_inv <<={};WH(t != m_external){cc_num_inv[cc_num[m_G.Enumeration_inv(t)]= count]<<= t;t = Next();}count++;}}}RE{MO(cc_num),MO(cc_num_inv),count};}TE VE VBFS::GetNodeEnumeration(){VE AN{};T t = Next();WH(t != m_external){AN <<= t;t = Next();}RE AN;}TE VE VBFS::GetReversedNodeEnumeration(){VE AN{},next{};T t;bool searched;WH(!(searched =(t = Next())== m_external)|| !next.empty()){WH(!next.empty()&&(searched || next.back()!= m_prev[m_G.Enumeration_inv(t)])){AN <<= next.back();pop(next);}if(!searched){next <<= t;}}RE AN;} TE CL BFS:PU VBFS{PU:TE IN BFS(GRAPH& G,CO T& external,Args&&... args);TE auto GetDistance()-> enable_if_t().edge())>>,Map>;TE auto GetDistance()-> enable_if_t().edge())>>,VE>;IN VO Push(LI>& next,CO T& t,CO T& p);}; TE TE IN BFS::BFS(GRAPH& G,CO T& external,Args&&... args):VBFS(G,external,forward(args)...){}TE TE auto BFS::GetDistance()-> enable_if_t().edge())>>,Map>{Map AN{};for(auto&[t,u]:TH->m_next){AN[t]= 0;}T t;WH((t = TH->Next())!= TH->m_external){if(AN.count(t)== 0){AN[t]= AN[TH->m_prev[TH->m_G.Enumeration_inv(t)]]+ 1;}}RE AN;}TE TE auto BFS::GetDistance()-> enable_if_t().edge())>>,VE>{VE AN(TH->SZ(),-1);for(auto&[t,p]:TH->m_next){AN[TH->m_G.Enumeration_inv(t)]= 0;}T t;WH((t = TH->Next())!= TH->m_external){auto&& i = TH->m_G.Enumeration_inv(t);AN[i]== -1?AN[i]= AN[TH->m_G.Enumeration_inv(TH->m_prev[i])]+ 1:AN[i];}RE AN;}TE IN VO BFS::Push(LI>& next,CO T& t,CO T& p){next <<={t,p};} #endif /* AAA 常設でないライブラリは以上に挿入する。*/ #define INCLUDE_SUB #include __FILE__ #else /* INCLUDE_LIBRARY */ #ifdef DEBUG #define _GLIBCXX_DEBUG #else #pragma GCC optimize ( "O3" ) #pragma GCC optimize ( "unroll-loops" ) #pragma GCC target ( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" ) #define DEXPR( LL , BOUND , VALUE1 , VALUE2 ) CEXPR( LL , BOUND , VALUE1 ) #define ASSERT( A , MIN , MAX ) AS( ( MIN ) <= A && A <= ( MAX ) ) #define REPEAT_MAIN( BOUND ) START_MAIN; CEXPR( int , test_case_num_bound , BOUND ); int test_case_num = 1; if CE( test_case_num_bound > 1 ){ FINISH_MAIN #ifdef USE_GETLINE #define SET_SEPARATE( SEPARATOR , ... ) VariadicGetline( cin , SEPARATOR , __VA_ARGS__ ) #define SET( ... ) SET_SEPARATE( '\n' , __VA_ARGS__ ) #define GETLINE_SEPARATE( SEPARATOR , ... ) string __VA_ARGS__; SET_SEPARATE( SEPARATOR , __VA_ARGS__ ) #define GETLINE( ... ) GETLINE_SEPARATE( '\n' , __VA_ARGS__ ) #define FINISH_MAIN GETLINE( test_case_num_str ); test_case_num = stoi( test_case_num_str ); ASSERT( test_case_num , 1 , test_case_num_bound ); } REPEAT( test_case_num ){ Solve(); } } #else #define SET( ... ) VariadicCin( cin , __VA_ARGS__ ) #define CIN( LL , ... ) LL __VA_ARGS__; SET( __VA_ARGS__ ) #define SET_A( I , N , ... ) VariadicResize( N + I , __VA_ARGS__ ); FOR( VARIABLE_FOR_SET_A , 0 , N ){ VariadicSet( cin , VARIABLE_FOR_SET_A + I , __VA_ARGS__ ); } #define CIN_A( LL , I , N , ... ) VE __VA_ARGS__; SET_A( I , N , __VA_ARGS__ ) #define CIN_AA( LL , I0 , N0 , I1 , N1 , VAR ) VE VAR( N0 + I0 , VE( N1 + I1 ) ); FOR( VARIABLE_FOR_CIN_AA , 0 , N0 ){ SET_A( I1 , N1 , VAR[VARIABLE_FOR_CIN_AA + I0] ); } #define FINISH_MAIN SET_ASSERT( test_case_num , 1 , test_case_num_bound ); } REPEAT( test_case_num ){ Solve(); } } #endif #define SET_ASSERT( A , MIN , MAX ) SET( A ); ASSERT( A , MIN , MAX ) #define SOLVE_ONLY #define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << ENDL #define COUTNS( ... ) VariadicCoutNonSep( cout , __VA_ARGS__ ) #define CERR( ... ) #define CERRNS( ... ) #define COUT_A( I , N , A ) CoutArray( cout , I , N , A ) << ENDL #define CERR_A( I , N , A ) #define WHAT( ... ) #define TLE( CONDITION ) if( !( CONDITION ) ){ cerr << "TLE" << endl; ll TLE_VAR = 1; while( TLE_VAR != 0 ){ ( TLE_VAR += 2 ) %= int( 1e9 ); } cerr << TLE_VAR << endl; } #define MLE( CONDITION ) if( !( CONDITION ) ){ cerr << "MLE" << endl; vector> MLE_VAR{}; REPEAT( 1e6 ){ MLE_VAR.push_back( vector( 1e6 ) ); } cerr << MLE_VAR << endl; } #define OLE( CONDITION ) if( !( CONDITION ) ){ cerr << "OLE" << endl; REPEAT( 1e8 ){ COUT( "OLE" ); } } #endif #ifdef REACTIVE #ifndef DEBUG #define LOCAL( ... ) #define RSET( A , ... ) SET( A ) #endif #define RCIN( LL , A , ... ) LL A; RSET( A , __VA_ARGS__ ) #define ENDL endl #else #define ENDL "\n" #endif #include using namespace std; #define ATT __attribute__( ( target( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" ) ) ) #define START_MAIN int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr ) #define START_WATCH chrono::system_clock::time_point watch = chrono::system_clock::now(); double loop_average_time = 0.0 , loop_start_time = loop_average_time , current_time = loop_start_time; int loop_count = current_time; assert( loop_count == 0 ) #define CURRENT_TIME ( current_time = static_cast( chrono::duration_cast( chrono::system_clock::now() - watch ).count() / 1000.0 ) ) #define CHECK_WATCH( TL_MS ) ( CURRENT_TIME , loop_count == 0 ? loop_start_time = current_time : loop_average_time = ( current_time - loop_start_time ) / loop_count , ++loop_count , current_time < TL_MS - loop_average_time * 2 - 100.0 ) #define CEXPR( LL , BOUND , VALUE ) CE LL BOUND = VALUE #define SET_A_ASSERT( I , N , A , MIN , MAX ) FOR( VARIABLE_FOR_SET_A , 0 , N ){ SET_ASSERT( A[VARIABLE_FOR_SET_A + I] , MIN , MAX ); } #define SET_AA_ASSERT( I0 , N0 , I1 , N1 , A , MIN , MAX ) FOR( VARIABLE_FOR_SET_AA0 , 0 , N0 ){ FOR( VARIABLE_FOR_SET_AA1 , 0 , N1 ){ SET_ASSERT( A[VARIABLE_FOR_SET_AA0 + I0][VARIABLE_FOR_SET_AA1 + I1] , MIN , MAX ); } } #define CIN_ASSERT( A , MIN , MAX ) decldecay_t( MAX ) A; SET_ASSERT( A , MIN , MAX ) #define CIN_A_ASSERT( I , N , A , MIN , MAX ) vector A( N + I ); SET_A_ASSERT( I , N , A , MIN , MAX ) #define CIN_AA_ASSERT( I0 , N0 , I1 , N1 , A , MIN , MAX ) vector A( N0 + I0 , vector( N1 + I1 ) ); SET_AA_ASSERT( I0 , N0 , I1 , N1 , A , MIN , MAX ) #define PR1( A1 , ... ) A1 #define PR2( A1 , A2 , ... ) A2 #define PR3( A1 , A2 , A3 , ... ) A3 #define FOR_( VAR , INITIAL , FINAL , UPPER , COMP , INCR ) for( decldecay_t( UPPER ) VAR = INITIAL ; VAR COMP ( FINAL ) ; VAR INCR ) #define FOR( VAR , INITIAL , ... ) FOR_( VAR , INITIAL , PR1( __VA_ARGS__ ) , PR1( __VA_ARGS__ ) , < , PR3( __VA_ARGS__ , += PR2( __VA_ARGS__ , ? ) , ++ ) ) #define FOREQ( VAR , INITIAL , ... ) FOR_( VAR , INITIAL , PR1( __VA_ARGS__ ) , PR1( __VA_ARGS__ ) , <= , PR3( __VA_ARGS__ , += PR2( __VA_ARGS__ , ? ) , ++ ) ) #define FOREQINV( VAR , INITIAL , ... ) FOR_( VAR , INITIAL , PR1( __VA_ARGS__ ) , INITIAL , + 1 > , PR3( __VA_ARGS__ , -= PR2( __VA_ARGS__ , ? ) , -- ) ) #define ITR( ARRAY ) auto begin_ ## ARRAY = ARRAY .BE() , itr_ ## ARRAY = begin_ ## ARRAY , end_ ## ARRAY = ARRAY .EN() #define FOR_ITR( ARRAY ) for( ITR( ARRAY ) , itr = itr_ ## ARRAY ; itr_ ## ARRAY != end_ ## ARRAY ; itr_ ## ARRAY ++ , itr++ ) #define RUN( ARRAY , ... ) for( auto&& __VA_ARGS__ : ARRAY ) #define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT , 0 , HOW_MANY_TIMES ) #define SET_PRECISION( DECIMAL_DIGITS ) cout << fixed << setprecision( DECIMAL_DIGITS ); cerr << fixed << setprecision( DECIMAL_DIGITS ) #define RETURN( ... ) SOLVE_ONLY; COUT( __VA_ARGS__ ); RE #define COMPARE( ... ) auto naive = Naive( __VA_ARGS__ , false ); auto answer = Answer( __VA_ARGS__ , false ); bool match = naive == answer; CERR( "(" , #__VA_ARGS__ , ") == (" , __VA_ARGS__ , ") : Naive ==" , naive , match ? "==" : "!=" , answer , "== Answer" ); if( !match ){ CERR( "出力の不一致が検出されました。" ); RE; } #define CHECK( ... ) auto answer = Answer( __VA_ARGS__ , false ); CERR( "(" , #__VA_ARGS__ , ") == (" , __VA_ARGS__ , ") : Answer == " , answer ) /* 圧縮用 */ #define TE template #define TY typename #define US using #define ST static #define AS assert #define IN inline #define CL class #define PU public #define OP operator #define CE constexpr #define CO const #define NE noexcept #define RE return #define WH while #define VO void #define VE vector #define LI list #define BE begin #define EN end #define SZ size #define LE length #define MO move #define TH this #define CRI CO int& #define CRUI CO uint& #define CRL CO ll& #define VI virtual #define IS basic_istream #define OS basic_ostream #define ST_AS static_assert #define reMO_CO remove_const #define is_COructible_v is_constructible_v #define rBE rbegin /* 型のエイリアス */ #define decldecay_t(VAR)decay_t TE US ret_t = decltype(declval()(declval()...)); TE US inner_t = TY T::type; US uint = unsigned int; US ll = long long; US ull = unsigned long long; US ld = long double; US lld = __float128; /* VVV 常設ライブラリは以下に挿入する。*/ #ifdef DEBUG #include "C:/Users/user/Documents/Programming/Contest/Template/Local/a_Body.hpp" US MP = DMod; // US MP = Mod

; #else /* Random (1KB)*/ ll GetRand(CRL Rand_min,CRL Rand_max){AS(Rand_min <= Rand_max);ll AN = time(NULL);RE AN * rand()%(Rand_max + 1 - Rand_min)+ Rand_min;} /* Set (2KB)*/ #define DC_OF_HASH(...)struct hash<__VA_ARGS__>{IN size_t OP()(CO __VA_ARGS__& n)CO;}; CL is_ordered{PU:is_ordered()= delete;TE ST CE auto Check(CO T& t)-> decltype(t < t,true_type());ST CE false_type Check(...);TE ST CE CO bool value = is_same_v< decltype(Check(declval())),true_type >;}; TE US Set = conditional_t>,unordered_set,conditional_t,set,VO>>; #define DF_OF_POP_FOR_SET(SET)TE IN T pop_max(SET& S){AS(!S.empty());auto IT = --S.EN();T AN = *IT;S.erase(IT);RE AN;}TE IN T pop_min(SET& S){AS(!S.empty());auto IT = S.BE();T AN = *IT;S.erase(IT);RE AN;}TE IN SET& OP<<=(SET& S,T t){S.insert(MO(t));RE S;}TE IN SET& OP<<=(SET& S,U&& u){S.insert(T{forward(u)});RE S;}TE IN SET& OP>>=(SET& S,CO T& t){auto IT = S.find(t);if(IT != S.EN()){S.erase(IT);}RE S;}TE IN SET& OP>>=(SET& S,CO U& u){RE S >>= T{u};}TE IN CO T& Get(CO SET& S,int i){auto BE = S.BE(),EN = S.EN();auto& IT = i < 0?(++i,--EN):BE;WH(i > 0 && IT != EN){--i;++IT;}WH(i < 0 && IT != BE){++i;--IT;}AS(i == 0);RE *IT;} #define DF_OF_UNION_FOR_SET(SET)TE IN SET& OP|=(SET& S0,SET S1){S0.merge(MO(S1));RE S0;}TE IN SET OP|(SET S0,SET S1){RE MO(S0.SZ()< S1.SZ()?S1 |= MO(S0):S0 |= MO(S1));} TE IN TY SET::const_iterator MaximumLeq(CO SET& S,CO T& t){auto IT = S.upper_bound(t);RE IT == S.BE()?S.EN():--IT;}TE IN TY SET::const_iterator MaximumLt(CO SET& S,CO T& t){auto IT = S.lower_bound(t);RE IT == S.BE()?S.EN():--IT;}TE IN TY SET::const_iterator MinimumGeq(CO SET& S,CO T& t){RE S.lower_bound(t);}TE IN TY SET::const_iterator MinimumGt(CO SET& S,CO T& t){RE S.upper_bound(t);}TE IN VO EraseBack(SET& S,ITERATOR& IT){IT = S.erase(IT);}TE IN VO EraseFront(SET& S,ITERATOR& IT){IT = S.erase(IT);IT == S.BE()?IT = S.EN():--IT;}TE TY SET,TY T,TY...Args> IN bool In(CO T& t,CO SET& S){RE S.count(t)> 0;}DF_OF_POP_FOR_SET(set);DF_OF_POP_FOR_SET(unordered_set);DF_OF_POP_FOR_SET(multiset);DF_OF_POP_FOR_SET(unordered_multiset);DF_OF_UNION_FOR_SET(set);DF_OF_UNION_FOR_SET(unordered_set);DF_OF_UNION_FOR_SET(multiset);DF_OF_UNION_FOR_SET(unordered_multiset);DF_OF_UNION_FOR_SET(VE);DF_OF_UNION_FOR_SET(LI); /* Tuple (6KB)*/ #define DF_OF_AR_FOR_TUPLE(OPR)TE TY PAIR> IN auto OP OPR ## =(PAIR& t0,CO PAIR& t1)-> decltype((get<0>(t0),t0))&{get<0>(t0)OPR ## = get<0>(t1);get<1>(t0)OPR ## = get<1>(t1);RE t0;}TE TY TUPLE> IN auto OP OPR ## =(TUPLE& t0,CO TUPLE& t1)-> decltype((get<0>(t0),t0))&{get<0>(t0)OPR ## = get<0>(t1);get<1>(t0)OPR ## = get<1>(t1);get<2>(t0)OPR ## = get<2>(t1);RE t0;}TE TY TUPLE> IN auto OP OPR ## =(TUPLE& t0,CO TUPLE& t1)-> decltype((get<0>(t0),t0))&{get<0>(t0)OPR ## = get<0>(t1);get<1>(t0)OPR ## = get<1>(t1);get<2>(t0)OPR ## = get<2>(t1);get<3>(t0)OPR ## = get<3>(t1);RE t0;}TE TY PAIR> IN auto OP OPR ## =(PAIR& t0,CO ARG& t1)-> decltype((get<0>(t0),t0))&{get<0>(t0)OPR ## = t1;get<1>(t0)OPR ## = t1;RE t0;}TE TY TUPLE> IN auto OP OPR ## =(TUPLE& t0,CO ARG& t1)-> decltype((get<0>(t0),t0))&{get<0>(t0)OPR ## = t1;get<1>(t0)OPR ## = t1;get<2>(t0)OPR ## = t1;RE t0;}TE TY TUPLE> IN auto OP OPR ## =(TUPLE& t0,CO ARG& t1)-> decltype((get<0>(t0),t0))&{get<0>(t0)OPR ## = t1;get<1>(t0)OPR ## = t1;get<2>(t0)OPR ## = t1;get<3>(t0)OPR ## = t1;RE t0;}TE TY TUPLE,TY...ARGS,TY ARG> IN auto OP OPR(CO TUPLE& t0,CO ARG& t1)-> decldecay_t((get<0>(t0),t0)){auto t = t0;RE MO(t OPR ## = t1);} #define DF_OF_INCREMENT_FOR_TUPLE(INCR)TE TY PAIR> IN auto OP INCR(PAIR& t)-> decltype((get<0>(t),t))&{INCR get<0>(t);INCR get<1>(t);RE t;}TE TY TUPLE> IN auto OP INCR(TUPLE& t)-> decltype((get<0>(t),t))&{INCR get<0>(t);INCR get<1>(t);INCR get<2>(t);RE t;}TE TY TUPLE> IN auto OP INCR(TUPLE& t)-> decltype((get<0>(t),t))&{INCR get<0>(t);INCR get<1>(t);INCR get<2>(t);INCR get<3>(t);RE t;} TE IN IS& OP>>(IS& is,tuple& arg){RE is >> get<0>(arg);}TE TY V> IN auto OP>>(IS& is,V& arg)-> decltype((get<0>(arg),is))&{RE is >> get<0>(arg)>> get<1>(arg);}TE IN IS& OP>>(IS& is,tuple& arg){RE is >> get<0>(arg)>> get<1>(arg)>> get<2>(arg);}TE IN IS& OP>>(IS& is,tuple& arg){RE is >> get<0>(arg)>> get<1>(arg)>> get<2>(arg)>> get<3>(arg);}TE IN OS& OP<<(OS& os,CO tuple& arg){RE os << get<0>(arg);}TE TY V> IN auto OP<<(OS& os,CO V& arg)-> decltype((get<0>(arg),os))&{RE os << get<0>(arg)<< " " << get<1>(arg);}TE IN OS& OP<<(OS& os,CO tuple& arg){RE os << get<0>(arg)<< " " << get<1>(arg)<< " " << get<2>(arg);}TE IN OS& OP<<(OS& os,CO tuple& arg){RE os << get<0>(arg)<< " " << get<1>(arg)<< " " << get<2>(arg)<< " " << get<3>(arg);}DF_OF_AR_FOR_TUPLE(+);TE TY V> IN auto OP-(CO V& t)-> decldecay_t((get<0>(t),t)){RE{-get<0>(t),-get<1>(t)};}TE IN tuple OP-(CO tuple& t){RE{-get<0>(t),-get<1>(t),-get<2>(t)};}TE IN tuple OP-(CO tuple& t){RE{-get<0>(t),-get<1>(t),-get<2>(t),-get<3>(t)};}DF_OF_AR_FOR_TUPLE(-);DF_OF_AR_FOR_TUPLE(*);DF_OF_AR_FOR_TUPLE(/);DF_OF_AR_FOR_TUPLE(%);DF_OF_INCREMENT_FOR_TUPLE(++);DF_OF_INCREMENT_FOR_TUPLE(--); TE CL TupleAccessIndex{};TE CL Tuple:PU tuple{PU:IN Tuple(Types&&... args);TE IN Tuple(Args&&... args);TE IN auto& OP[](CO TupleAccessIndex& i)NE;TE IN CO auto& OP[](CO TupleAccessIndex& i)CO NE;};TE CL tuple_size>:PU tuple_size>{};TE CL tuple_element>:PU tuple_element>{}; TE US Pair = Tuple;TE US T2 = Pair;TE US T3 = Tuple;TE US T4 = Tuple; CE TupleAccessIndex<0> O{};CE TupleAccessIndex<1> I{};CE TupleAccessIndex<2> II{};CE TupleAccessIndex<3> III{}; TE IN Tuple::Tuple(Types&&... args):tuple(MO(args)...){}TE TE IN Tuple::Tuple(Args&&... args):tuple(forward(args)...){}TE TE IN auto& Tuple::OP[](CO TupleAccessIndex& i)NE{RE get(*TH);}TE TE IN CO auto& Tuple::OP[](CO TupleAccessIndex& i)CO NE{RE get(*TH);}TE TY PAIR,TY INT> T2 cast(CO PAIR& t){RE{get<0>(t),get<1>(t)};}TE T3 cast(CO tuple& t){RE{get<0>(t),get<1>(t),get<2>(t)};}TE T4 cast(CO tuple& t){RE{get<0>(t),get<1>(t),get<2>(t),get<3>(t)};} #define DF_OF_HASH_FOR_TUPLE(PAIR)TE IN size_t hash>::OP()(CO PAIR& n)CO{ST CO size_t seed =(GetRand(1e3,1e8)<< 1)| 1;ST CO hash h0;ST CO hash h1;RE(h0(get<0>(n))* seed)^ h1(get<1>(n));} TE DC_OF_HASH(tuple);TE DC_OF_HASH(pair);TE DC_OF_HASH(tuple);TE DC_OF_HASH(tuple);TE DC_OF_HASH(tuple); TE IN size_t hash>::OP()(CO tuple& n)CO{ST CO hash h;RE h(get<0>(n));}DF_OF_HASH_FOR_TUPLE(pair);DF_OF_HASH_FOR_TUPLE(tuple);TE IN size_t hash>::OP()(CO tuple& n)CO{ST CO size_t seed =(GetRand(1e3,1e8)<< 1)| 1;ST CO hash> h01;ST CO hash h2;RE(h01({get<0>(n),get<1>(n)})* seed)^ h2(get<2>(n));}TE IN size_t hash>::OP()(CO tuple& n)CO{ST CO size_t seed =(GetRand(1e3,1e8)<< 1)| 1;ST CO hash> h01;ST CO hash> h23;RE(h01({get<0>(n),get<1>(n)})* seed)^ h23({get<2>(n),get<3>(n)});} /* Vector (3KB)*/ #define DF_OF_COUT_FOR_VE(V)TE IN OS& OP<<(OS& os,CO V& arg){auto BE = arg.BE(),EN = arg.EN();auto IT = BE;WH(IT != EN){(IT == BE?os:os << " ")<< *IT;IT++;}RE os;} DF_OF_COUT_FOR_VE(VE);DF_OF_COUT_FOR_VE(LI);DF_OF_COUT_FOR_VE(set);DF_OF_COUT_FOR_VE(unordered_set);DF_OF_COUT_FOR_VE(multiset);IN VO VariadicResize(CRI SZ){}TE IN VO VariadicResize(CRI SZ,Arg& arg,ARGS&... args){arg.resize(SZ);VariadicResize(SZ,args...);} #define DF_OF_AR_FOR_VE(V,OPR)TE IN V& OP OPR ## =(V& a0,CO V& a1){AS(a0.SZ()<= a1.SZ());auto IT0 = a0.BE(),EN0 = a0.EN();auto IT1 = a1.BE();WH(IT0 != EN0){*(IT0++)OPR ## = *(IT1++);}RE a0;}TE IN V& OP OPR ## =(V& a,CO T& t){for(auto& x:a){x OPR## = t;}RE a;}TE IN V OP OPR(V a,CO U& u){RE MO(a OPR ## = u);} #define DF_OF_INCREMENT_FOR_VE(V,INCR)TE IN V& OP INCR(V& a){for(auto& i:a){INCR i;}RE a;} #define DF_OF_SHIFT_FOR_VE(V)TE IN V& OP<<=(V& a,T t){a.push_back(MO(t));RE a;}TE IN V& OP<<=(V& a,U&& u){RE a <<= forward(u);}TE IN T pop(V& a){AS(!a.empty());T AN = MO(a.back());a.pop_back();RE AN;} #define DF_OF_ARS_FOR_VE(V)DF_OF_AR_FOR_VE(V,+);DF_OF_AR_FOR_VE(V,-);DF_OF_AR_FOR_VE(V,*);DF_OF_AR_FOR_VE(V,/);DF_OF_AR_FOR_VE(V,%);DF_OF_INCREMENT_FOR_VE(V,++);DF_OF_INCREMENT_FOR_VE(V,--);TE IN V OP-(V a){RE MO(a *= T(-1));}TE IN V OP*(CO T& t,V v){RE MO(v *= t);}DF_OF_SHIFT_FOR_VE(V); #define DF_FOR_VE_BOOL(OPR)IN VE::reference OP OPR ## =(VE::reference b0,CO bool& b1){RE MO(b0 = bool(b0)OPR b1);}IN VE& OP OPR ## =(VE& b0,CO VE& b1){CO int L = b0.SZ();for(int i = 0;i < L;i++){b0[i]OPR ## = b1[i];}RE b0;}IN VE OP OPR(VE b0,CO VE& b1){RE MO(b0 OPR ## = b1);} DF_OF_ARS_FOR_VE(VE);DF_OF_ARS_FOR_VE(LI);DF_OF_SHIFT_FOR_VE(basic_string); TE IN auto Get(V& a){RE[&](CRI i = 0)-> CO decldecay_t(a[0])&{RE a[i];};}TE IN VE id(CRI SZ){VE AN(SZ);for(int i = 0;i < SZ;i++){AN[i]= i;}RE AN;}TE IN VO Sort(V& a,CO bool& reversed = false){US T = decldecay_t(a[0]);if(reversed){ST auto comp =[](CO T& t0,CO T& t1){RE t1 < t0;};sort(a.BE(),a.EN(),comp);}else{sort(a.BE(),a.EN());}}TE IN VO Sort(V0& a,V1& b,CO bool& reversed = false){CO int SZ = a.SZ();AS(SZ == int(b.SZ()));VE> v(SZ);for(int i = 0;i < SZ;i++){v[i]={MO(a[i]),MO(b[i])};}Sort(v,reversed);for(int i = 0;i < SZ;i++){a[i]= MO(v[i].first);b[i]= MO(v[i].second);}}TE IN pair,VE> IndexSort(CO V& a,CO bool& reversed = false){CO int SZ = a.SZ();auto index = id(SZ),ord = index;sort(index.BE(),index.EN(),[&](CRI i,CRI j){CO pair ti{a[i],i},tj{a[j],j};RE reversed?tj < ti:ti < tj;});for(int i = 0;i < SZ;i++){ord[index[i]]= i;}RE{MO(index),MO(ord)};}TE IN int len(CO V& a){RE a.SZ();}TE IN VO Reverse(V& a){CO int SZ = len(a),half = SZ / 2;for(int i = 0;i < half;i++){swap(a[i],a[SZ-1-i]);}};TE IN V Reversed(V a){Reverse(a);RE MO(a);}TE TY V,TY T> IN V cast(CO V& a){V AN{};for(auto& x:a){AN <<= x;}RE AN;} DF_FOR_VE_BOOL(&);DF_FOR_VE_BOOL(|);DF_FOR_VE_BOOL(^); /* Map (1KB)*/ #define DF_OF_AR_FOR_MAP(MAP,OPR)TE IN MAP& OP OPR ## =(MAP& a,CO pair& v){a[v.first]OPR ## = v.second;RE a;}TE IN MAP& OP OPR ## =(MAP& a0,CO MAP& a1){for(auto&[t,u]:a1){a0[t]OPR ## = u;}RE a0;}TE IN MAP OP OPR(MAP a,CO ARG& arg){RE MO(a OPR ## = arg);} #define DF_OF_ARS_FOR_MAP(MAP)DF_OF_AR_FOR_MAP(MAP,+);DF_OF_AR_FOR_MAP(MAP,-);DF_OF_AR_FOR_MAP(MAP,*);DF_OF_AR_FOR_MAP(MAP,/);DF_OF_AR_FOR_MAP(MAP,%); TE US Map = conditional_t>,unordered_map,conditional_t,map,VO>>; DF_OF_ARS_FOR_MAP(map);DF_OF_ARS_FOR_MAP(unordered_map); /* StdStream (2KB)*/ TE IN IS& VariadicCin(IS& is){RE is;}TE IN IS& VariadicCin(IS& is,Arg& arg,ARGS&... args){RE VariadicCin(is >> arg,args...);}TE IN IS& VariadicSet(IS& is,CRI i){RE is;}TE IN IS& VariadicSet(IS& is,CRI i,Arg& arg,ARGS&... args){RE VariadicSet(is >> arg[i],i,args...);}TE IN IS& VariadicGetline(IS& is,CO char& separator){RE is;}TE IN IS& VariadicGetline(IS& is,CO char& separator,Arg& arg,ARGS&... args){RE VariadicGetline(getline(is,arg,separator),separator,args...);}TE IN OS& VariadicCout(OS& os,Arg&& arg){RE os << forward(arg);}TE IN OS& VariadicCout(OS& os,Arg1&& arg1,Arg2&& arg2,ARGS&&... args){RE VariadicCout(os << forward(arg1)<< " ",forward(arg2),forward(args)...);}TE IN OS& VariadicCoutNonSep(OS& os,Arg&& arg){RE os << forward(arg);}TE IN OS& VariadicCoutNonSep(OS& os,Arg1&& arg1,Arg2&& arg2,ARGS&&... args){RE VariadicCoutNonSep(os << forward(arg1),forward(arg2),forward(args)...);}TE IN OS& CoutArray(OS& os,CRI i_start,CRI i_ulim,ARRAY&& a){for(int i = i_start;i < i_ulim;i++){(i == i_start?os:(os << " "))<< a[i];}RE os;} /* Module (6KB)*/ #define DC_OF_CPOINT(POINT)IN CO U& POINT()CO NE #define DC_OF_POINT(POINT)IN U& POINT()NE #define DF_OF_CPOINT(POINT)TE IN CO U& VirtualPointedSet::POINT()CO NE{RE Point();} #define DF_OF_POINT(POINT)TE IN U& VirtualPointedSet::POINT()NE{RE Point();} TE CL UnderlyingSet{PU:US type = U;};TE CL VirtualPointedSet:VI PU UnderlyingSet{PU:VI CO U& Point()CO NE = 0;VI U& Point()NE = 0;DC_OF_CPOINT(Unit);DC_OF_CPOINT(Zero);DC_OF_CPOINT(One);DC_OF_CPOINT(Infty);DC_OF_POINT(init);DC_OF_POINT(root);};TE CL PointedSet:VI PU VirtualPointedSet{PU:U m_b_U;IN PointedSet(U b_u = U());IN CO U& Point()CO NE;IN U& Point()NE;};TE CL VirtualNSet:VI PU UnderlyingSet{PU:VI U Transfer(CO U& u)= 0;IN U Inverse(CO U& u);};TE CL AbstractNSet:VI PU VirtualNSet{PU:F_U m_f_U;IN AbstractNSet(F_U f_U);IN AbstractNSet& OP=(CO AbstractNSet&)NE;IN U Transfer(CO U& u);};TE CL VirtualMagma:VI PU UnderlyingSet{PU:VI U Product(U u0,CO U& u1)= 0;IN U Sum(U u0,CO U& u1);};TE CL AdditiveMagma:VI PU VirtualMagma{PU:IN U Product(U u0,CO U& u1);};TE CL MultiplicativeMagma:VI PU VirtualMagma{PU:IN U Product(U u0,CO U& u1);};TE CL AbstractMagma:VI PU VirtualMagma{PU:M_U m_m_U;IN AbstractMagma(M_U m_U);IN AbstractMagma& OP=(CO AbstractMagma&)NE;IN U Product(U u0,CO U& u1);}; TE IN PointedSet::PointedSet(U b_U):m_b_U(MO(b_U)){}TE IN CO U& PointedSet::Point()CO NE{RE m_b_U;}TE IN U& PointedSet::Point()NE{RE m_b_U;}DF_OF_CPOINT(Unit);DF_OF_CPOINT(Zero);DF_OF_CPOINT(One);DF_OF_CPOINT(Infty);DF_OF_POINT(init);DF_OF_POINT(root);TE IN AbstractNSet::AbstractNSet(F_U f_U):m_f_U(MO(f_U)){ST_AS(is_invocable_r_v);}TE IN AbstractNSet& AbstractNSet::operator=(CO AbstractNSet&)NE{RE *TH;}TE IN U AbstractNSet::Transfer(CO U& u){RE m_f_U(u);}TE IN U VirtualNSet::Inverse(CO U& u){RE Transfer(u);}TE IN AbstractMagma::AbstractMagma(M_U m_U):m_m_U(MO(m_U)){ST_AS(is_invocable_r_v);}TE IN AbstractMagma& AbstractMagma::OP=(CO AbstractMagma&)NE{RE *TH;}TE IN U AdditiveMagma::Product(U u0,CO U& u1){RE MO(u0 += u1);}TE IN U MultiplicativeMagma::Product(U u0,CO U& u1){RE MO(u0 *= u1);}TE IN U AbstractMagma::Product(U u0,CO U& u1){RE m_m_U(MO(u0),u1);}TE IN U VirtualMagma::Sum(U u0,CO U& u1){RE Product(MO(u0),u1);} TE CL VirtualMonoid:VI PU VirtualMagma,VI PU VirtualPointedSet{};TE CL AdditiveMonoid:VI PU VirtualMonoid,PU AdditiveMagma,PU PointedSet{};TE CL MultiplicativeMonoid:VI PU VirtualMonoid,PU MultiplicativeMagma,PU PointedSet{PU:IN MultiplicativeMonoid(U e_U);};TE CL AbstractMonoid:VI PU VirtualMonoid,PU AbstractMagma,PU PointedSet{PU:IN AbstractMonoid(M_U m_U,U e_U);}; TE IN MultiplicativeMonoid::MultiplicativeMonoid(U e_U):PointedSet(MO(e_U)){}TE IN AbstractMonoid::AbstractMonoid(M_U m_U,U e_U):AbstractMagma(MO(m_U)),PointedSet(MO(e_U)){} TE CL VirtualGroup:VI PU VirtualMonoid,VI PU VirtualPointedSet,VI PU VirtualNSet{};TE CL AdditiveGroup:VI PU VirtualGroup,PU AdditiveMonoid{PU:IN U Transfer(CO U& u);};TE CL AbstractGroup:VI PU VirtualGroup,PU AbstractMonoid,PU AbstractNSet{PU:IN AbstractGroup(M_U m_U,U e_U,I_U i_U);}; TE IN AbstractGroup::AbstractGroup(M_U m_U,U e_U,I_U i_U):AbstractMonoid(MO(m_U),MO(e_U)),AbstractNSet(MO(i_U)){}TE IN U AdditiveGroup::Transfer(CO U& u){RE -u;} TE CL VirtualRSet:VI PU UnderlyingSet{PU:VI U Action(CO R& r,U u)= 0;IN U Power(U u,CO R& r);IN U ScalarProduct(CO R& r,U u);};TE >CL RegularRSet:VI PU VirtualRSet,PU MAGMA{PU:IN RegularRSet(MAGMA magma);IN U Action(CO U& r,U u);};TE CL AbstractRSet:VI PU VirtualRSet{PU:O_U m_o_U;IN AbstractRSet(CO R& dummy0,CO U& dummy1,O_U o_U);IN AbstractRSet& OP=(CO AbstractRSet&)NE;IN U Action(CO R& r,U u);};TE >CL AbstractModule:PU AbstractRSet,PU GROUP{PU:IN AbstractModule(CO R& dummy,O_U o_U,GROUP M);};TE CL Module:VI PU VirtualRSet,PU AdditiveGroup{PU:IN U Action(CO R& r,U u);}; TE IN RegularRSet::RegularRSet(MAGMA magma):MAGMA(MO(magma)){}TE IN AbstractRSet::AbstractRSet(CO R& dummy0,CO U& dummy1,O_U o_U):m_o_U(MO(o_U)){ST_AS(is_invocable_r_v);}TE IN AbstractModule::AbstractModule(CO R& dummy,O_U o_U,GROUP M):AbstractRSet(dummy,M.One(),MO(o_U)),GROUP(MO(M)){ST_AS(is_same_v>);}TE IN AbstractRSet& AbstractRSet::OP=(CO AbstractRSet&)NE{RE *TH;}TE IN U RegularRSet::Action(CO U& r,U u){RE TH->Product(r,MO(u));}TE IN U AbstractRSet::Action(CO R& r,U u){RE m_o_U(r,MO(u));}TE IN U Module::Action(CO R& r,U u){RE MO(u *= r);}TE IN U VirtualRSet::Power(U u,CO R& r){RE Action(r,MO(u));}TE IN U VirtualRSet::ScalarProduct(CO R& r,U u){RE Action(r,MO(u));} /* Graph (5KB)*/ TE CL VirtualGraph:VI PU UnderlyingSet{PU:VI R1 Enumeration(CRI i)= 0;IN R2 Enumeration_inv(CO T& t);TE IN R2 Enumeration_inv(CO PATH& p);IN VO Reset();VI CRI SZ()CO NE = 0;VI E& edge()NE = 0;VI ret_t Edge(CO T& t)= 0;TE IN ret_t Edge(CO PATH& p);ST IN CO T& Vertex(CO T& t)NE;TE ST IN CO T& Vertex(CO PATH& e)NE;VI R2 Enumeration_inv_Body(CO T& t)= 0;};TE CL EdgeImplimentation:VI PU VirtualGraph{PU:int m_SZ;E m_edge;IN EdgeImplimentation(CRI SZ,E edge);IN CRI SZ()CO NE;IN E& edge()NE;IN ret_t Edge(CO T& t);};TE CL Graph:PU EdgeImplimentation{PU:IN Graph(CRI SZ,E edge);IN CRI Enumeration(CRI i);TE IN Graph GetGraph(F edge)CO;IN CRI Enumeration_inv_Body(CRI t);};TE CL EnumerationGraph:PU EdgeImplimentation,ret_t,E>{PU:Enum_T m_enum_T;Enum_T_inv m_enum_T_inv;IN EnumerationGraph(CRI SZ,Enum_T enum_T,Enum_T_inv enum_T_inv,E edge);IN ret_t Enumeration(CRI i);TE IN EnumerationGraph GetGraph(F edge)CO;IN ret_t Enumeration_inv_Body(CO T& t);};TE EnumerationGraph(CRI SZ,Enum_T enum_T,Enum_T_inv enum_T_inv,E edge)-> EnumerationGraph()(0)),Enum_T,Enum_T_inv,E>;TE CL MemorisationGraph:PU EdgeImplimentation{PU:int m_LE;VE m_memory;Map m_memory_inv;IN MemorisationGraph(CRI SZ,CO T& dummy,E edge);IN T Enumeration(CRI i);IN VO Reset();TE IN MemorisationGraph GetGraph(F edge)CO;IN CRI Enumeration_inv_Body(CO T& t);}; TE IN EdgeImplimentation::EdgeImplimentation(CRI SZ,E edge):m_SZ(SZ),m_edge(MO(edge)){ST_AS(is_COructible_v && is_COructible_v && is_invocable_v);}TE IN Graph::Graph(CRI SZ,E edge):EdgeImplimentation(SZ,MO(edge)){}TE IN EnumerationGraph::EnumerationGraph(CRI SZ,Enum_T enum_T,Enum_T_inv enum_T_inv,E edge):EdgeImplimentation,ret_t,E>(SZ,MO(edge)),m_enum_T(MO(enum_T)),m_enum_T_inv(MO(enum_T_inv)){}TE IN MemorisationGraph::MemorisationGraph(CRI SZ,CO T& dummy,E edge):EdgeImplimentation(SZ,MO(edge)),m_LE(),m_memory(),m_memory_inv(){ST_AS(is_invocable_v);}TE IN CRI Graph::Enumeration(CRI i){RE i;}TE IN ret_t EnumerationGraph::Enumeration(CRI i){RE m_enum_T(i);}TE IN T MemorisationGraph::Enumeration(CRI i){AS(0 <= i && i < m_LE);RE m_memory[i];}TE IN R2 VirtualGraph::Enumeration_inv(CO T& t){RE Enumeration_inv_Body(t);}TE TE IN R2 VirtualGraph::Enumeration_inv(CO PATH& p){RE Enumeration_inv_Body(get<0>(p));}TE IN CRI Graph::Enumeration_inv_Body(CRI i){RE i;}TE IN ret_t EnumerationGraph::Enumeration_inv_Body(CO T& t){RE m_enum_T_inv(t);}TE IN CRI MemorisationGraph::Enumeration_inv_Body(CO T& t){if(m_memory_inv.count(t)== 0){AS(m_LE < TH->SZ());m_memory.push_back(t);RE m_memory_inv[t]= m_LE++;}RE m_memory_inv[t];}TE VO VirtualGraph::Reset(){}TE IN VO MemorisationGraph::Reset(){m_LE = 0;m_memory.clear();m_memory_inv.clear();}TE IN CRI EdgeImplimentation::SZ()CO NE{RE m_SZ;}TE IN E& EdgeImplimentation::edge()NE{RE m_edge;}TE IN ret_t EdgeImplimentation::Edge(CO T& t){RE m_edge(t);}TE TE IN ret_t VirtualGraph::Edge(CO PATH& p){RE Edge(get<0>(p));}TE TE IN Graph Graph::GetGraph(F edge)CO{RE Graph(TH->SZ(),MO(edge));}TE TE IN EnumerationGraph EnumerationGraph::GetGraph(F edge)CO{RE EnumerationGraph(TH->SZ(),m_enum_T,m_enum_T_inv,MO(edge));}TE TE IN MemorisationGraph MemorisationGraph::GetGraph(F edge)CO{RE MemorisationGraph(TH->SZ(),MO(edge));}TE IN CO T& VirtualGraph::Vertex(CO T& t)NE{RE t;}TE TE IN CO T& VirtualGraph::Vertex(CO PATH& e)NE{RE Vertex(get<0>(e));} /* Grid (3KB)*/ #define SET_GRID Hm = H - 1;Wm = W - 1;HW = ll{H}* W #define SET_HW(h,w)H = h;W = w;SET_GRID #define CIN_HW SET(H,W);SET_GRID TE CL GridGraph:PU EnumerationGraph,T2(&)(CRI),int(&)(CO T2&),E>{PU:IN GridGraph(E e);};int H,W,Hm,Wm;ll HW;VE grid;char walkable = '.';CO string direction="URDL";VE> grid_edge ={{false,true,false},{true,false,true},{false,true,false}}; IN T2 EnumHW(CRI v){RE{v / W,v % W};}IN int EnumHW_inv(CO T2& ij){auto&[i,j]= ij;RE i * W + j;}TE IN GridGraph::GridGraph(E e):EnumerationGraph,T2(&)(CRI),int(&)(CO T2&),E>(HW,EnumHW,EnumHW_inv,MO(e)){AS(HW >> 31 == 0 && H * W == HW);}VE> EdgeOnGrid(CO T2& v){VE> AN{};auto&[i,j]= v;if(grid[i][j]== walkable){for(int di = -1;di <= 1;di++){CO int ni = i + di;if(0 <= ni && ni < H){for(int dj = -1;dj <= 1;dj++){CO int nj = j + dj;if(grid_edge[di+1][dj+1]&& 0 <= nj && nj < W && grid[ni][nj]== walkable){AN <<={ni,nj};}}}}}RE AN;}VE,ll>> WEdgeOnGrid(CO T2& v){VE,ll>> AN{};auto&[i,j]= v;if(grid[i][j]== walkable){for(int di = -1;di <= 1;di++){CO int ni = i + di;if(0 <= ni && ni < H){for(int dj = -1;dj <= 1;dj++){CO int nj = j + dj;if(grid_edge[di+1][dj+1]&& 0 <= nj && nj < W && grid[ni][nj]== walkable){AN <<={{ni,nj},1};}}}}}RE AN;}IN VO SetWallStringOnGrid(){grid.resize(H);for(int i = 0;i < H;i++){SET(grid[i]);AS(int(grid[i].SZ())== W);}}IN int DirectionNumberOnGrid(CRI i,CRI j,CRI k,CRI h,CO bool& xy_axis = false){RE xy_axis?i < k?1:i > k?3:j < h?0:j > h?2:-1:i < k?2:i > k?0:j < h?1:j > h?3:-1;}IN int DirectionNumberOnGrid(CO T2& v,CO T2& w,CO bool& xy_axis = false){auto&[i,j]= v;auto&[k,h]= w;RE DirectionNumberOnGrid(i,j,k,h);}IN int DirectionNumberOnGrid(CRI v,CRI w,CO bool& xy_axis = false){RE DirectionNumberOnGrid(EnumHW(v),EnumHW(w));}IN int DirectionNumberOnGrid(CO char& c){RE c == 'U'?0:c == 'R'?1:c == 'D'?2:c == 'L'?3:-1;}IN int ReverseDirectionNumberOnGrid(CRI n){AS(0 <= n && n < 4);RE n ^ 2;}IN T2 DirectionVEOnGrid(CO char& c,CO bool& xy_axis = false){CO int n = DirectionNumberOnGrid(c);AS(n != -1);RE T2{xy_axis?n == 1?1:n == 3?-1:0:n == 0?-1:n == 2?1:0,xy_axis?n == 0?1:n == 2?-1:0:n == 1?1:n == 3?-1:0};} /* Loop (1KB)*/ TE bool NextLoop(CRI SZ,CO VE& lower_bound,CO VE& upper_limit,VE& index){int depth = 0;WH(depth < SZ){if(++index[depth]< upper_limit[depth]){break;}index[depth]= lower_bound[depth];depth++;}RE depth < SZ;}TE bool NextLoop(CO VE& lower_bound,CO VE& upper_limit,VE& index){RE NextLoop(index.SZ(),lower_bound,upper_limit,index);}TE bool NextLoopEq(CRI SZ,CO VE& lower_bound,CO VE& upper_bound,VE& index){int depth = 0;WH(depth < SZ){if(++index[depth]<= upper_bound[depth]){break;}index[depth]= lower_bound[depth];depth++;}RE depth < SZ;}TE bool NextLoopEq(CO VE& lower_bound,CO VE& upper_bound,VE& index){RE NextLoopEq(index.SZ(),lower_bound,upper_bound,index);} /* string (1KB)*/ TE IN char IntToChar(CO INT& i,CO char& c = 'a'){RE c + i;}TE IN INT CharToInt(CO char& i){RE i -(i < 'a'?'A':'a');}TE string ArrayToString(CO VE& A,CO char& c = 'a'){CO int N = A.SZ();string S(N,c);for(int i = 0;i < N;i++){S[i]= IntToChar(A[i],c);}RE S;}TE VE StringToArray(CO string& S){CO int N = S.SZ();VE A(N);for(int i = 0;i < N;i++){A[i]= CharToInt(S[i]);}RE A;}TE string ArrayToParenthesisString(CO VE& A){CO int N = A.SZ();string S(N,'(');for(int i = 0;i < N;i++){AS(0 <= A[i]&& A[i]<= 1);S[i]= "()"[A[i]];}RE S;}TE VE ParenthesisStringToArray(CO string& S){CO int N = S.SZ();VE A(N);for(int i = 0;i < N;i++){A[i]= S[i]- '(';}RE A;} #endif /* AAA 常設ライブラリは以上に挿入する。*/ #define INCLUDE_LIBRARY #include __FILE__ #endif /* INCLUDE_LIBRARY */ #endif /* INCLUDE_SUB */ #endif /* INCLUDE_MAIN */