#include #include #include #include #include using namespace std; #define MAIN main #define TYPE_OF( VAR ) remove_const::type >::type #define UNTIE ios_base::sync_with_stdio( false ); cin.tie( nullptr ) #define CEXPR( LL , BOUND , VALUE ) constexpr const LL BOUND = VALUE #define CIN( LL , A ) LL A; cin >> A #define ASSERT( A , MIN , MAX ) assert( MIN <= A && A <= MAX ) #define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( TYPE_OF( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ ) #define QUIT return 0 #define RETURN( ANSWER ) cout << ( ANSWER ) << "\n"; QUIT #include class Veblen { public: string m_a; string m_b; inline Veblen() : m_a() , m_b() {}; inline Veblen( const string& a , const string& b ) : m_a( a ) , m_b( b ) {}; }; class Order { public: inline Order() = default; list AdditionArray( const string& N ) const; bool operator()( const string& N , const string& M ) const; bool operator()( const Veblen& N , const Veblen& M ) const; string VNF( const string& N ) const; Veblen VNF( const Veblen& N ) const; }; list Order::AdditionArray( const string& N ) const { list S{}; int layer = 0; int i_left = -1; int i_mid = -1; int size = N.size(); static string L = "("; static string R = ")"; FOR( i , 0 , size ){ string c = N.substr( i , 1 ); if( c == L ){ if( layer == 0 ){ i_left = i; } layer++; } else if( c == R ){ layer--; if( layer == 0 ){ assert( i_left >= 0 && i_mid >= 0 ); S.push_back( Veblen( N.substr( i_left + 1 , i_mid - i_left - 1 ) , N.substr( i_mid + 1 , i - i_mid - 1 ) ) ); } } else { if( layer == 1 ){ i_mid = i; } } } return S; } bool Order::operator()( const string& N , const string& M ) const { list A_N = move( AdditionArray( N ) ); list A_M = move( AdditionArray( M ) ); auto itr_N = A_N.begin(); auto end_N = A_N.end(); auto itr_M = A_M.begin(); auto end_M = A_M.end(); while( itr_N != end_N && itr_M != end_M ){ Veblen& Ni = *itr_N; Veblen& Mi = *itr_M; if( operator()( Ni , Mi ) ){ return true; } else if( operator()( Mi , Ni ) ){ return false; } itr_N++; itr_M++; } return itr_M != end_M; } bool Order::operator()( const Veblen& N , const Veblen& M ) const { if( operator()( N.m_a , M.m_a ) ){ list A_N_b = move( AdditionArray( N.m_b ) ); int size_N_b = A_N_b.size(); if( size_N_b == 0 ){ return true; } return operator()( A_N_b.front() , M ); } else if( operator()( M.m_a , N.m_a ) ){ list A_M_b = move( AdditionArray( M.m_b ) ); int size_M_b = A_M_b.size(); if( size_M_b == 0 ){ return false; } Veblen& b_copy = A_M_b.front(); if( operator()( N , b_copy ) ){ return true; } else if( size_M_b == 1 ){ return false; } return ! operator()( b_copy , N ); } return operator()( N.m_b , M.m_b ); } string Order::VNF( const string& N ) const { list A_N = move( AdditionArray( N ) ); auto begin = A_N.begin(); auto end = A_N.end(); if( begin == end ){ return ""; } auto itr = begin; auto itr_prev = itr; { Veblen& A_N_i = *itr; A_N_i = VNF( A_N_i ); itr++; } while( itr != end ){ Veblen& A_N_i = *itr; A_N_i = VNF( A_N_i ); itr_prev++; itr++; } itr = itr_prev; bool searching = ( itr != begin ); while( searching ){ Veblen& A_N_i = *itr; bool increasing = true; while( increasing ){ itr_prev = itr; itr_prev--; Veblen& A_N_i_prev = *itr_prev; if( operator()( A_N_i_prev , A_N_i ) ){ if( itr_prev == begin ){ A_N.erase( itr_prev ); increasing = false; searching = false; } else { A_N.erase( itr_prev ); } } else { increasing = false; } } if( searching ){ searching = ( --itr != begin ); } } string answer{}; itr = A_N.begin(); while( itr != end ){ answer += "(" + itr->m_a + "|" + itr->m_b + ")"; itr++; } return answer; } Veblen Order::VNF( const Veblen& N ) const { string a = VNF( N.m_a ); string b = VNF( N.m_b ); list A_b = move( AdditionArray( b ) ); Veblen N_copy = Veblen( a , b ); if( A_b.size() != 1 ){ return N_copy; } Veblen& b_VNF = A_b.front(); if( operator()( b_VNF , N_copy ) ){ return N_copy; } return b_VNF; } int MAIN() { UNTIE; CEXPR( int , length , 30 ); CIN( string , T_0 ); int size_0 = T_0.size(); ASSERT( size_0 , 3 , length ); CIN( string , T_1 ); int size_1 = T_1.size(); ASSERT( size_1 , 3 , length ); Order ord{}; RETURN( ord( ord.VNF( T_1 ) , ord.VNF( T_0 ) ) ? 0 : 1 ); }