#include using namespace std; using uint = unsigned int; using ll = long long; #define CIN( LL , A ) LL A; cin >> A #define GETLINE( A ) string A; getline( cin , A ) #define GETLINE_SEPARATE( A , SEPARATOR ) string A; getline( cin , A , SEPARATOR ) #define FOR_LL( VAR , INITIAL , FINAL_PLUS_ONE ) for( ll VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ ) #define FOR_ITR( ARRAY , ITR , END ) for( auto ITR = ARRAY .begin() , END = ARRAY .end() ; ITR != END ; ITR ++ ) #define REPEAT( HOW_MANY_TIMES ) FOR_LL( VARIABLE_FOR_REPEAT , 0 , HOW_MANY_TIMES ) #define RETURN( ANSWER ) cout << ( ANSWER ) << endl; return 0 #define DOUBLE( PRECISION , ANSWER ) cout << fixed << setprecision( PRECISION ) << ( ANSWER ) << endl; return 0 #define MIN( A , B ) A < B ? A : B; #define MAX( A , B ) A < B ? B : A; template inline T Distance( const T& a , const T& b ){ return a < b ? b - a : a - b; } // 自分のライブラリ(https://github.com/p-adic/cpp)よりソースコードをコピーして編集している。 using uint = unsigned int; template class VLArray; template class IteratorOfVLArray; template class ConstIteratorOfVLArray; template class EntryOfVLArray { friend VLArray; friend IteratorOfVLArray; friend ConstIteratorOfVLArray; private: T m_t; EntryOfVLArray* m_prev; EntryOfVLArray* m_next; private: inline EntryOfVLArray(); template inline EntryOfVLArray( const Arg& ); template inline EntryOfVLArray( const Arg& , EntryOfVLArray* const& , EntryOfVLArray* const& ); }; template inline EntryOfVLArray::EntryOfVLArray() : m_t() , m_prev( this ) , m_next( this ) {} template template inline EntryOfVLArray::EntryOfVLArray( const Arg& t ) : m_t( t ) , m_prev( this ) , m_next( this ) {} template template inline EntryOfVLArray::EntryOfVLArray( const Arg& t , EntryOfVLArray* const& prev , EntryOfVLArray* const& next ) : m_t( t ) , m_prev( prev ) , m_next( next ) {} template class EntryOfVLArray; template class ConstIteratorOfVLArray; template class VLArray; template class IteratorOfVLArray { friend ConstIteratorOfVLArray; friend VLArray; private: // ++の実装のためにはm_pをポインタへの参照にできない。 EntryOfVLArray* m_p; public: inline IteratorOfVLArray( EntryOfVLArray* const& ) noexcept; inline IteratorOfVLArray( const IteratorOfVLArray& ) noexcept; // inline T& Access() const; inline T& operator*() const; inline T* operator->() const; IteratorOfVLArray& operator=( const IteratorOfVLArray& ) noexcept; inline void operator++( int ); inline void operator--( int ); }; template class ConstIteratorOfVLArray { friend VLArray; private: const EntryOfVLArray* m_p; public: inline ConstIteratorOfVLArray( EntryOfVLArray* const& ) noexcept; inline ConstIteratorOfVLArray( const ConstIteratorOfVLArray& ) noexcept; inline ConstIteratorOfVLArray( const IteratorOfVLArray& ) noexcept; inline const T& operator*() const; inline const T* operator->() const; ConstIteratorOfVLArray& operator=( const ConstIteratorOfVLArray& ) noexcept; ConstIteratorOfVLArray& operator=( const IteratorOfVLArray& ) noexcept; inline void operator++( int ); inline void operator--( int ); static inline bool Equal( const IteratorOfVLArray& , const IteratorOfVLArray& ) noexcept; static inline bool Equal( const ConstIteratorOfVLArray& , const IteratorOfVLArray& ) noexcept; static inline bool Equal( const IteratorOfVLArray& , const ConstIteratorOfVLArray& ) noexcept; static inline bool Equal( const ConstIteratorOfVLArray& , const ConstIteratorOfVLArray& ) noexcept; }; template inline bool operator==( const IteratorOfVLArray& , const IteratorOfVLArray& ) noexcept; template inline bool operator!=( const IteratorOfVLArray& , const IteratorOfVLArray& ) noexcept; template inline bool operator==( const ConstIteratorOfVLArray& , const IteratorOfVLArray& ) noexcept; template inline bool operator!=( const ConstIteratorOfVLArray& , const IteratorOfVLArray& ) noexcept; template inline bool operator==( const IteratorOfVLArray& , const ConstIteratorOfVLArray& ) noexcept; template inline bool operator!=( const IteratorOfVLArray& , const ConstIteratorOfVLArray& ) noexcept; template inline bool operator==( const ConstIteratorOfVLArray& , const ConstIteratorOfVLArray& ) noexcept; template inline bool operator!=( const ConstIteratorOfVLArray& , const ConstIteratorOfVLArray& ) noexcept; // IteratorOfVLArray template inline IteratorOfVLArray::IteratorOfVLArray( EntryOfVLArray* const& p ) noexcept : m_p( p ) {} template inline IteratorOfVLArray::IteratorOfVLArray( const IteratorOfVLArray& itr ) noexcept : m_p( itr.m_p ) {} // template inline T& IteratorOfVLArray::Access() const { return Access( m_p ).m_t; } template inline T& IteratorOfVLArray::operator*() const { return ( *m_p ).m_t; } template inline T* IteratorOfVLArray::operator->() const { return &( *( *this ) ); } template IteratorOfVLArray& IteratorOfVLArray::operator=( const IteratorOfVLArray& itr ) noexcept { m_p = itr.m_p; return *this; } template inline void IteratorOfVLArray::operator++( int ){ m_p = ( *m_p ).m_next; } template inline void IteratorOfVLArray::operator--( int ){ m_p = ( *m_p ).m_prev; } // ConstIteratorOfVLArray template inline ConstIteratorOfVLArray::ConstIteratorOfVLArray( EntryOfVLArray* const& p ) noexcept : m_p( p ) {} template inline ConstIteratorOfVLArray::ConstIteratorOfVLArray( const ConstIteratorOfVLArray& itr ) noexcept : m_p( itr.m_p ) {} template inline ConstIteratorOfVLArray::ConstIteratorOfVLArray( const IteratorOfVLArray& itr ) noexcept : m_p( itr.m_p ) {} template inline const T& ConstIteratorOfVLArray::operator*() const { return ( *m_p ).m_t; }; template inline const T* ConstIteratorOfVLArray::operator->() const { return &( *( *this ) ); } template ConstIteratorOfVLArray& ConstIteratorOfVLArray::operator=( const ConstIteratorOfVLArray& itr ) noexcept { m_p = itr.m_p; return *this; } template ConstIteratorOfVLArray& ConstIteratorOfVLArray::operator=( const IteratorOfVLArray& itr ) noexcept { m_p = itr.m_p; return *this; } template inline void ConstIteratorOfVLArray::operator++( int ) { m_p = ( *m_p ).m_next; } template inline void ConstIteratorOfVLArray::operator--( int ) { m_p = ( *m_p ).m_prev; } template inline bool ConstIteratorOfVLArray::Equal( const IteratorOfVLArray& itr0 , const IteratorOfVLArray& itr1 ) noexcept { return itr0.m_p == itr1.m_p; } template inline bool ConstIteratorOfVLArray::Equal( const ConstIteratorOfVLArray& itr0 , const IteratorOfVLArray& itr1 ) noexcept { return itr0.m_p == itr1.m_p; } template inline bool ConstIteratorOfVLArray::Equal( const IteratorOfVLArray& itr0 , const ConstIteratorOfVLArray& itr1 ) noexcept { return itr0.m_p == itr1.m_p; } template inline bool ConstIteratorOfVLArray::Equal( const ConstIteratorOfVLArray& itr0 , const ConstIteratorOfVLArray& itr1 ) noexcept { return itr0.m_p == itr1.m_p; } template inline bool operator==( const IteratorOfVLArray& itr0 , const IteratorOfVLArray& itr1 ) noexcept { return ConstIteratorOfVLArray::Equal( itr0 , itr1 ); } template inline bool operator!=( const IteratorOfVLArray& itr0 , const IteratorOfVLArray& itr1 ) noexcept { return !( itr0 == itr1 );} template inline bool operator==( const ConstIteratorOfVLArray& itr0 , const IteratorOfVLArray& itr1 ) noexcept { return ConstIteratorOfVLArray::Equal( itr0 , itr1 ); } template inline bool operator!=( const ConstIteratorOfVLArray& itr0 , const IteratorOfVLArray& itr1 ) noexcept { return !( itr0 == itr1 );} template inline bool operator==( const IteratorOfVLArray& itr0 , const ConstIteratorOfVLArray& itr1 ) noexcept { return ConstIteratorOfVLArray::Equal( itr0 , itr1 ); } template inline bool operator!=( const IteratorOfVLArray& itr0 , const ConstIteratorOfVLArray& itr1 ) noexcept { return !( itr0 == itr1 );} template inline bool operator==( const ConstIteratorOfVLArray& itr0 , const ConstIteratorOfVLArray& itr1 ) noexcept { return ConstIteratorOfVLArray::Equal( itr0 , itr1 ); } template inline bool operator!=( const ConstIteratorOfVLArray& itr0 , const ConstIteratorOfVLArray& itr1 ) noexcept { return !( itr0 == itr1 );} template class SingletonType { protected: SingletonType() = default; SingletonType( const SingletonType& ) = default; virtual ~SingletonType() = default; SingletonType& operator=( const SingletonType& ) = default; public: static T& GetUniqueObject(); }; template class SingletonOf : public SingletonType > { friend SingletonType >; private: SingletonOf() = default; SingletonOf( const SingletonOf& ) = default; ~SingletonOf() = default; SingletonOf& operator=( const SingletonOf& ) = default; public: using type = T; }; // Replace TYPE_NAME by a suitable typename. /* class TYPE_NAME : public SingletonType { friend SingletonType; private: TYPE_NAME() = default; TYPE_NAME( const TYPE_NAME& ) = default; ~TYPE_NAME() = default; TYPE_NAME& operator=( const TYPE_NAME& ) = default; }; */ template T& Object(); #include template T& SingletonType::GetUniqueObject() { static T t; return t; } template T& Object() { // if( ! is_base_of,T>::value ){ // ERR_IMPUT( typeid( T ) ); // } return T::GetUniqueObject(); } template class WrappedInt : public SingletonType > { friend class SingletonType >; private: WrappedInt() = default; WrappedInt( const WrappedInt& ) = default; WrappedInt& operator=( const WrappedInt& ) = default; static const int m_i; public: static int Get(); }; template class WrappedUInt : public SingletonType > { friend class SingletonType >; private: WrappedUInt() = default; WrappedUInt( const WrappedUInt& ) = default; WrappedUInt& operator=( const WrappedUInt& ) = default; static const uint m_i; public: static uint Get(); }; template const WrappedInt& Wrap(); template const WrappedUInt& WrapU(); template const int WrappedInt::m_i = i; template const uint WrappedUInt::m_i = i; template int WrappedInt::Get() { return m_i; } template uint WrappedUInt::Get() { return m_i; } template const WrappedInt& Wrap() { return Object >(); } template const WrappedUInt& WrapU() { return Object >(); } class EmptySet { private: EmptySet(); EmptySet( const EmptySet& ); EmptySet& operator=( const EmptySet& ); }; template class VLArray; template class VLMatrix_Body; template class VLMatrix_Body,T> { public: using type = VLArray; }; template class VLMatrix_Body,T> { public: using type = VLArray,T>::type>; }; template class VLMatrix_Body,T> { public: using type = VLArray,T>::type>; }; template using VLMatrix = typename VLMatrix_Body,T>::type; template class IteratorOfVLArray; template class ConstIteratorOfVLArray; template class WrappedType; template class VLArray { private: EntryOfVLArray m_e; EntryOfVLArray* const m_p_e; uint m_size; public: // Tは引数0のコンストラクタを持つクラスのみ許容。 inline VLArray(); template inline VLArray( const Arg1& , const Arg2&... ); inline VLArray( const VLArray& ); // Tが引数0のコンストラクタを持たないクラスの場合に使用。 template inline VLArray( const WrappedType& t ); virtual ~VLArray(); VLArray& operator=( const VLArray& ); inline const uint& size() const noexcept; inline void clear(); inline bool empty() const noexcept; T& front(); const T& front() const; T& back(); const T& back() const; template void push_back( const Arg& ); template void push_back( const Args&... ); template void push_front( const Arg& ); // 前から順にpush_frontする。 template void push_front( const Args&... ); void pop_back(); void pop_front(); template inline void Concatenate( const Args&... ); template void Concatenate_back( const Arg& ); template void Concatenate_back( const Args&... ); template void Concatenate_front( const Arg& ); // 前から順にConcatenate_frontする。 template void Concatenate_front( const Args&... ); using iterator = IteratorOfVLArray; using const_iterator = ConstIteratorOfVLArray; // *thisがconstである場合に確実にconst_iterator返しをするために、iterator返しは非constにする必要がある。 inline iterator begin() noexcept; inline const_iterator begin() const noexcept; inline iterator end() noexcept; inline const_iterator end() const noexcept; template void insert( const iterator& , const Arg& ); template void insert_front( const iterator& , const Arg& ); template void insert_back( const iterator& , const Arg& ); iterator erase( iterator& ); iterator erase_back( iterator& ); iterator erase_front( iterator& ); T& operator[]( const uint& ); const T& operator[]( const uint& ) const; VLArray GetInitialSegment( const int& ) const; VLArray GetFinalSegment( const int& ) const; bool CheckContain( const iterator& ) const noexcept; bool CheckContain( const const_iterator& ) const noexcept; string Display() const; private: template inline int push_back_int( const Arg& ); template inline int push_front_int( const Arg& ); template inline int Concatenate_back_int( const Arg& ); template inline int Concatenate_front_int( const Arg& ); template static inline void ExpandParameterPack( const Args&... ) noexcept; }; template bool operator==( const VLArray& , const VLArray& ); template inline bool operator!=( const VLArray& , const VLArray& ); template VLArray to_VLArray( const uint& , const T& ); template inline VLMatrix<1,T> to_VLMatrix( const uint& , const T& ); template inline VLMatrix<2,T> to_VLMatrix( const uint& , const uint& , const T& ); template inline VLMatrix<3,T> to_VLMatrix( const uint& , const uint& , const uint& , const T& ); template VLArray Frown( const Arg&... ); template T Sum( const VLArray& ); template class WrappedType { private: Arg m_t; public: template inline WrappedType( const ARGS&... args ); inline void Set( const Arg& t ); inline const Arg& Get() const noexcept; }; template class WrappedTypes {}; template template inline WrappedType::WrappedType( const ARGS&... args ) : m_t( args... ) {} template inline void WrappedType::Set( const Arg& t ){ m_t = t; } template inline const Arg& WrappedType::Get() const noexcept { return m_t; } template inline VLArray::VLArray() : m_e() , m_p_e( &m_e ) , m_size( 0 ) {} template template inline VLArray::VLArray( const Arg1& t0 , const Arg2&... t1 ) : VLArray() { push_back( t0 , t1... ); } template inline VLArray::VLArray( const VLArray& a ) : m_e( a.m_e.m_t ) , m_p_e( &m_e ) , m_size( 0 ) { Concatenate( a ); } template template inline VLArray::VLArray( const WrappedType& t ) : m_e( t.Get() ) , m_p_e( &m_e ) , m_size( 0 ) {} template VLArray::~VLArray() { clear(); } template VLArray& VLArray::operator=( const VLArray& a ) { if( this != &a ){ clear(); Concatenate( a ); } return *this; } template inline const uint& VLArray::size() const noexcept { return m_size; } template inline void VLArray::clear(){ while( m_size > 0 ) pop_back(); } template inline bool VLArray::empty() const noexcept { return m_size == 0; } template T& VLArray::front() { // if( m_size == 0 ){ // ERR_CALL; // } return m_e.m_next->m_t; } template const T& VLArray::front() const { // if( m_size == 0 ){ // ERR_CALL; // } return m_e.m_next->m_t; } template T& VLArray::back() { // if( m_size == 0 ){ // ERR_CALL; // } return m_e.m_prev->m_t; } template const T& VLArray::back() const { // if( m_size == 0 ){ // ERR_CALL; // } return m_e.m_prev->m_t; } template template void VLArray::push_back( const Arg& t ) { EntryOfVLArray* p_e_prev = m_e.m_prev; auto p = new EntryOfVLArray( t , p_e_prev , m_p_e ); m_e.m_prev = p; p_e_prev->m_next = p; m_size++; return; } template template void VLArray::push_back( const Args&... args ) { VLArray copy{}; // 関数の処理は後ろからなのでbackではなくfrontを使う。 ExpandParameterPack( copy.push_front_int( args )... ); Concatenate_back( copy ); return; } template template inline int VLArray::push_back_int( const Arg& t ) { push_back( t ); return 0; } template template void VLArray::push_front( const Arg& t ) { EntryOfVLArray* p_b = m_e.m_next; auto p = new EntryOfVLArray( t , m_p_e , p_b ); p_b->m_prev = p; m_e.m_next = p; m_size++; return; } template template void VLArray::push_front( const Args&... args ) { VLArray copy{}; // 関数の処理は後ろからなのでfrontではなくbackを使う。 ExpandParameterPack( copy.push_back_int( args )... ); Concatenate_front( copy ); return; } template template inline int VLArray::push_front_int( const Arg& t ) { push_front( t ); return 0; } template void VLArray::pop_back() { // if( m_size == 0 ){ // ERR_CALL; // } EntryOfVLArray* p_e_prev = m_e.m_prev; EntryOfVLArray* p_e_prev_prev = p_e_prev->m_prev; m_e.m_prev = p_e_prev_prev; p_e_prev_prev->m_next = m_p_e; delete p_e_prev; m_size--; return; } template void VLArray::pop_front() { // if( m_size == 0 ){ // ERR_CALL; // } EntryOfVLArray* p_b = m_e.m_next; EntryOfVLArray* p_b_next = ( *p_b ).m_next; p_b_next->m_prev = m_p_e; m_e.m_next = p_b_next; delete p_b; m_size--; return; } template template inline void VLArray::Concatenate( const Args&... args ) { Concatenate_back( args... ); } template template void VLArray::Concatenate_back( const Arg& a ) { const EntryOfVLArray* p = a.m_p_e; const uint& N = a.m_size; for( uint n = 0 ; n < N ; n++ ){ p = p->m_next; push_back( p->m_t ); } return; } template template void VLArray::Concatenate_back( const Args&... args ) { VLArray copy{}; // 関数の処理は後ろからなのでbackではなくfrontを使う。 ExpandParameterPack( copy.Concatenate_front_int( args )... ); Concatenate_back( copy ); return; } template template inline int VLArray::Concatenate_back_int( const Arg& a ) { Concatenate( a ); return 0; } template template void VLArray::Concatenate_front( const Arg& a ) { const EntryOfVLArray* p = a.m_p_e; const uint& N = a.m_size; for( uint n = 0 ; n < N ; n++ ){ p = p->m_prev; push_front( p->m_t ); } return; } template template void VLArray::Concatenate_front( const Args&... args ) { VLArray copy{}; // 関数の処理は後ろからなのでfrontではなくbackを使う。 ExpandParameterPack( copy.Concatenate_back_int( args )... ); Concatenate_front( copy ); return; } template template inline int VLArray::Concatenate_front_int( const Arg& a ) { Concatenate_front( a ); return 0; } template inline typename VLArray::iterator VLArray::begin() noexcept { return IteratorOfVLArray( m_e.m_next ); } template inline typename VLArray::const_iterator VLArray::begin() const noexcept { return ConstIteratorOfVLArray( m_e.m_next ); } template inline typename VLArray::iterator VLArray::end() noexcept { return IteratorOfVLArray( m_p_e ); } template inline typename VLArray::const_iterator VLArray::end() const noexcept { return ConstIteratorOfVLArray( m_p_e ); } template template inline void VLArray::insert( const typename VLArray::iterator& itr , const Arg& t ) { insert_back( itr , t ); } template template void VLArray::insert_front( const typename VLArray::iterator& itr , const Arg& t ) { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr , t ); // } if( itr == begin() ){ push_front( t ); } else { EntryOfVLArray* p1 = itr.m_p; EntryOfVLArray* p0 = p1->m_prev; auto p = new EntryOfVLArray( t , p0 , p1 ); p0->m_next = p; p1->m_prev = p; m_size++; } return; } template template void VLArray::insert_back( const typename VLArray::iterator& itr , const Arg& t ) { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr , t ); // } EntryOfVLArray* p0 = itr.m_p; EntryOfVLArray* p1 = p0->m_next; auto p = new EntryOfVLArray( t , p0 , p1 ); p1->m_prev = p; p0->m_next = p; m_size++; return; } template inline typename VLArray::iterator VLArray::erase( typename VLArray::iterator& itr ) { return erase_back( itr ); } template typename VLArray::iterator VLArray::erase_back( typename VLArray::iterator& itr ) { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr ); // } EntryOfVLArray* p = itr.m_p; EntryOfVLArray* p0 = p->m_prev; EntryOfVLArray* p1 = p->m_next; p0->m_next = p1; p1->m_prev = p0; itr++; delete p; m_size--; return itr; } template typename VLArray::iterator VLArray::erase_front( typename VLArray::iterator& itr ) { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr ); // } EntryOfVLArray* p = itr.m_p; EntryOfVLArray* p0 = p->m_prev; EntryOfVLArray* p1 = p->m_next; p0->m_next = p1; p1->m_prev = p0; itr--; delete p; m_size--; return itr; } template T& VLArray::operator[]( const uint& i ) { // if( i >= m_size ){ // ERR_IMPUT( i ); // } if( i < m_size / 2 ){ EntryOfVLArray* p = m_e.m_next; for( uint n = 0 ; n < i ; n++ ){ p = p->m_next; } return p->m_t; } EntryOfVLArray* p = m_e.m_prev; for( uint n = m_size - 1 ; n > i ; n-- ){ p = p->m_prev; } return p->m_t; } template const T& VLArray::operator[]( const uint& i ) const { // if( i >= m_size ){ // ERR_IMPUT( i ); // } if( i < m_size / 2 ){ EntryOfVLArray* p = m_e.m_next; for( uint n = 0 ; n < i ; n++ ){ p = p->m_next; } return p->m_t; } EntryOfVLArray* p = m_e.m_prev; for( uint n = m_size - 1 ; n > i ; n-- ){ p = p->m_prev; } return p->m_t; } template VLArray VLArray::GetInitialSegment( const int& n ) const { const int N = (int)m_size; int M; if( N <= n ){ M = N; } else { if( 0 <= n ){ M = n; } else { M = N + n; } } VLArray b{}; const_iterator itr = begin(); for( int m = 1 ; m <= M ; m++ ){ b.push_back( *itr ); itr++; } return b; } template VLArray VLArray::GetFinalSegment( const int& n ) const { const int N = (int)m_size; int M; if( N <= n ){ M = N; } else { if( 0 <= n ){ M = n; } else { M = N + n; } } VLArray b{}; const_iterator itr = end(); for( int m = 1 ; m <= M ; m++ ){ itr--; b.push_front( *itr ); } return b; } template bool VLArray::CheckContain( const iterator& itr ) const noexcept { for( auto itr_b = begin() , itr_e = end() ; itr_b != itr_e ; itr_b++ ){ if( itr == itr_b ){ return true; } } return false; } template bool VLArray::CheckContain( const const_iterator& itr ) const noexcept { for( auto itr_b = begin() , itr_e = end() ; itr_b != itr_e ; itr_b++ ){ if( itr == itr_b ){ return true; } } return false; } template string VLArray::Display() const { string s = "("; EntryOfVLArray* p = m_p_e; for( uint n = 0 ; n < m_size ; n++ ){ p = p->m_next; if( n > 0 ){ s += ","; } s += to_string( p->m_t ); } s += ")"; return s; } template template inline void VLArray::ExpandParameterPack( const Args&... ) noexcept {}; template bool operator==( const VLArray& a1 , const VLArray& a2 ) { auto itr1 = a1.begin(); auto end1 = a1.end(); auto itr2 = a2.begin(); auto end2 = a2.end(); while( itr1 != end1 && itr2 != end2 ){ if( *itr1 != *itr2 ){ return false; } itr1++; itr2++; } return ( itr1 == end1 ) && ( itr2 == end2 ); } template inline bool operator!=( const VLArray& a1 , const VLArray& a2 ) { return !( a1 == a2 ); } template VLArray to_VLArray( const uint& N , const T& t ) { auto a = VLArray(); for( uint n = 0 ; n < N ; n++ ){ a.push_back( t ); } return a; } template inline VLMatrix<1,T> to_VLMatrix( const uint& N , const T& t ){ return to_VLArray( N , t ); } template inline VLMatrix<2,T> to_VLMatrix( const uint& N0 , const uint& N1 , const T& t ){ return to_VLArray( N1 , to_VLArray( N0 , t ) ); } template inline VLMatrix<3,T> to_VLMatrix( const uint& N0 , const uint& N1 , const uint& N2 , const T& t){ return to_VLArray( N2 , to_VLMatrix( N0 , N1 , t ) ); } template VLArray Frown( const Arg&... args ) { VLArray a{}; a.Concatenate( args... ); return a; } template T Sum( const VLArray& a ) { T t{}; for( auto itr = a.begin() , end = a.end() ; itr != end ; itr++ ){ t += *itr; } return t; } template INT Residue( const INT& M , const INT& n ) noexcept; template INT Residue( const INT& M , const INT& n ) noexcept { if( M == 0 ){ return 0; } const INT M_abs = ( M > 0 ? M : -M ); if( n < 0 ){ const INT n_abs = -n; const INT res = n_abs % M_abs; return res == 0 ? res : M_abs - res; } return n % M_abs; } using INT_TYPE_FOR_ADIC_INT = long long int; template class AdicInt { private: VLArray m_expansion; INT_TYPE_FOR_ADIC_INT m_n; public: inline AdicInt( const INT_TYPE_FOR_ADIC_INT& n ) noexcept; inline const VLArray& GetExpansion() const noexcept; inline const INT_TYPE_FOR_ADIC_INT& GetValue() const noexcept; static const VLArray& Expand( const INT_TYPE_FOR_ADIC_INT& n ) noexcept; }; template inline AdicInt::AdicInt( const INT_TYPE_FOR_ADIC_INT& n ) noexcept : m_expansion( Expand( n ) ) , m_n( n ) {} template inline const VLArray& AdicInt::GetExpansion() const noexcept { return m_expansion; } template inline const INT_TYPE_FOR_ADIC_INT& AdicInt::GetValue() const noexcept { return m_n; } template const VLArray& AdicInt::Expand( const INT_TYPE_FOR_ADIC_INT& n ) noexcept { static VLArray memory_n{}; static VLArray > memory_answer{}; if( P == 0 ){ // ダミー return memory_n; } auto itr_n = memory_n.begin() , end_n = memory_n.end(); auto itr_answer = memory_answer.begin(); while( itr_n != end_n ){ if( *itr_n == n ){ return *itr_answer; } itr_n++; itr_answer++; } INT_TYPE_FOR_ADIC_INT n_copy = n; VLArray answer{}; if( LENGTH == 0 ){ for( INT_TYPE_FOR_ADIC_INT i = 0 ; n_copy != 0 ; i++ ){ const INT_TYPE_FOR_ADIC_INT d = Residue( P , n_copy ); answer.push_back( d ); n_copy -= d; n_copy /= P; } } else { for( INT_TYPE_FOR_ADIC_INT i = 0 ; i < LENGTH && n_copy != 0 ; i++ ){ const INT_TYPE_FOR_ADIC_INT d = Residue( P , n_copy ); answer.push_back( d ); n_copy -= d; n_copy /= P; } } memory_n.push_back( n ); memory_answer.push_back( answer ); return memory_answer.back(); } // init * ( t ^ num ) template T Power( const T& t , const UINT& num , const T& init = 1 , const bool& for_right_multiplication = true , const string& method = "normal" ); template inline T PowerNormalMethod( const T& t , const UINT& num , const T& init = 1 , const bool& for_right_multiplication = true ); template T PowerBinaryMethod( const T& t , const UINT& num , const T& init = 1 , const bool& for_right_multiplication = true ); // 単なる2乗だが、T次第ではオーバーロードしてより高速なものに置き換える template inline T Square( const T& t ); // PowerBinaryMetodの呼び出しは部分特殊化ではなくオーバーロードで処理できるようにするためにPowerBinaryMethodとはしない。 template inline T Power( const T& t , const UINT& num , const T& init , const bool& for_right_multiplication , const string& method ) { return method == "binary" ? PowerBinaryMethod( t , num , init , for_right_multiplication ) : PowerNormalMethod( t , num , init , for_right_multiplication ); } template inline T PowerNormalMethod( const T& t , const UINT& num , const T& init , const bool& for_right_multiplication ) { return num == 0 ? init : ( for_right_multiplication ? PowerNormalMethod( t , num - 1 , init ) * t : t * PowerNormalMethod( t , num - 1 , init ) ); } template T PowerBinaryMethod( const T& t , const UINT& num , const T& init , const bool& for_right_multiplication ) { const VLArray& num_binary = AdicInt<2>::Expand( num ); T answer = init; T power = t; for( auto itr = num_binary.begin() , end = num_binary.end() ; itr != end ; itr++ ){ if( *itr == 1 ){ answer = for_right_multiplication ? answer * power : power * answer; } // 部分特殊化ではなくオーバーロードで処理できるようにするためにSquareとしない。 power = Square( power ); } return answer; } template inline T Square( const T& t ) { return t * t; } using INT_TYPE_FOR_MOD = long long int; // ここをtempate などにしてしまうとoperator+などを呼び出す際に型推論に失敗する。整数型を変えたい時はINT_TYPE_FOR_MODの型エイリアスを変更する。 template class Mod { protected: INT_TYPE_FOR_MOD m_n; INT_TYPE_FOR_MOD m_inv; public: inline Mod() noexcept; inline Mod( const INT_TYPE_FOR_MOD& n ) noexcept; inline Mod( const Mod& n ) noexcept; inline Mod& operator=( const INT_TYPE_FOR_MOD& n ) noexcept; Mod& operator=( const Mod& n ) noexcept; Mod& operator+=( const INT_TYPE_FOR_MOD& n ) noexcept; inline Mod& operator+=( const Mod& n ) noexcept; inline Mod& operator-=( const INT_TYPE_FOR_MOD& n ) noexcept; inline Mod& operator-=( const Mod& n ) noexcept; Mod& operator*=( const INT_TYPE_FOR_MOD& n ) noexcept; Mod& operator*=( const Mod& n ) noexcept; // INT_TYPE_FOR_MODでの割り算ではないことに注意 virtual Mod& operator/=( const INT_TYPE_FOR_MOD& n ); virtual Mod& operator/=( const Mod& n ); Mod& operator%=( const INT_TYPE_FOR_MOD& n ); inline Mod& operator%=( const Mod& n ); // 前置++/--を使うつもりがないので後置++/--と同じものとして定義する inline Mod& operator++() noexcept; inline Mod& operator++( int ) noexcept; inline Mod& operator--() noexcept; inline Mod& operator--( int ) noexcept; inline const INT_TYPE_FOR_MOD& Represent() const noexcept; void Invert() noexcept; bool CheckInvertible() noexcept; bool IsSmallerThan( const INT_TYPE_FOR_MOD& n ) const noexcept; bool IsBiggerThan( const INT_TYPE_FOR_MOD& n ) const noexcept; }; template inline bool operator==( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template inline bool operator==( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template inline bool operator==( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator==( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator!=( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template inline bool operator!=( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template inline bool operator!=( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator!=( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator<( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template inline bool operator<( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template inline bool operator<( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator<=( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template inline bool operator<=( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template inline bool operator<=( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator<=( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator>( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template inline bool operator>( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template inline bool operator>( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator>( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator>=( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template inline bool operator>=( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template inline bool operator>=( const Mod& n0 , const Mod& n1 ) noexcept; template inline bool operator>=( const Mod& n0 , const Mod& n1 ) noexcept; template Mod operator+( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template Mod operator+( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template Mod operator+( const Mod& n0 , const Mod& n1 ) noexcept; template inline Mod operator-( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template Mod operator-( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template Mod operator-( const Mod& n0 , const Mod& n1 ) noexcept; template Mod operator*( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept; template Mod operator*( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept; template Mod operator*( const Mod& n0 , const Mod& n1 ) noexcept; template Mod operator/( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ); template Mod operator/( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ); template Mod operator/( const Mod& n0 , const Mod& n1 ); template Mod operator%( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ); template inline Mod operator%( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ); template inline Mod operator%( const Mod& n0 , const Mod& n1 ); template Mod Inverse( const Mod& n ); template Mod Power( const Mod& n , const INT_TYPE_FOR_MOD& p , const string& method = "normal" ); template <> inline Mod<2> Power( const Mod<2>& n , const INT_TYPE_FOR_MOD& p , const string& method ); // M乗が1になるよう定義されていることに注意 template inline Mod Power( const Mod& n , const Mod& p , const string& method = "normal" ); template <> inline Mod<2> Power( const Mod<2>& n , const Mod<2>& p , const string& method ); // ../Power/a_Body.hppにて定義 template inline T Square( const T& t ); template <> inline Mod<2> Square >( const Mod<2>& t ); void LazyEvaluationOfModularInverse( const INT_TYPE_FOR_MOD& M , const INT_TYPE_FOR_MOD& n , INT_TYPE_FOR_MOD& m ); template inline Mod::Mod() noexcept : m_n( 0 ) , m_inv( M ){} template inline Mod::Mod( const INT_TYPE_FOR_MOD& n ) noexcept : m_n( Residue( M , n ) ) , m_inv( 0 ){} template inline Mod::Mod( const Mod& n ) noexcept : m_n( n.m_n ) , m_inv( 0 ){} template inline Mod& Mod::operator=( const INT_TYPE_FOR_MOD& n ) noexcept { return operator=( Mod( n ) ); } template Mod& Mod::operator=( const Mod& n ) noexcept { m_n = n.m_n; m_inv = n.m_inv; return *this; } template Mod& Mod::operator+=( const INT_TYPE_FOR_MOD& n ) noexcept { m_n = Residue( M , m_n + n ); m_inv = 0; return *this; } template inline Mod& Mod::operator+=( const Mod& n ) noexcept { return operator+=( n.m_n ); }; template inline Mod& Mod::operator-=( const INT_TYPE_FOR_MOD& n ) noexcept { return operator+=( -n ); } template inline Mod& Mod::operator-=( const Mod& n ) noexcept { return operator-=( n.m_n ); } template Mod& Mod::operator*=( const INT_TYPE_FOR_MOD& n ) noexcept { m_n = Residue( M , m_n * n ); m_inv = 0; return *this; } template Mod& Mod::operator*=( const Mod& n ) noexcept { m_n = Residue( M , m_n * n.m_n ); if( m_inv == 0 || n.m_inv == 0 ){ m_inv = 0; } else if( m_inv == M || n.m_inv == M ){ m_inv = M; } else { Residue( M , m_inv * n.m_inv ); } return *this; } // 仮想関数なのでinline指定しない。 template Mod& Mod::operator/=( const INT_TYPE_FOR_MOD& n ) { return operator/=( Mod( n ) ); } template Mod& Mod::operator/=( const Mod& n ) { return operator*=( Inverse( n ) ); } template Mod& Mod::operator%=( const INT_TYPE_FOR_MOD& n ) { m_n %= Residue( M , n ); m_inv = 0; return *this; } template inline Mod& Mod::operator%=( const Mod& n ) { return operator%=( n.m_n ); } template inline Mod& Mod::operator++() noexcept { return operator+=( 1 ); } template inline Mod& Mod::operator++( int ) noexcept { return operator++(); } template inline Mod& Mod::operator--() noexcept { return operator-=( 1 ); } template inline Mod& Mod::operator--( int ) noexcept { return operator-=(); } template inline const INT_TYPE_FOR_MOD& Mod::Represent() const noexcept { return m_n; } template void Mod::Invert() noexcept { if( CheckInvertible() ){ INT_TYPE_FOR_MOD i = m_inv; m_inv = m_n; m_n = i; } else { // m_nがMになるのはここの処理に限るのでRepresent()の値を参照することで例外処理可能 m_n = M; m_inv = M; } return; } template bool Mod::CheckInvertible() noexcept { if( m_inv == 0 ){ LazyEvaluationOfModularInverse( M , m_n , m_inv ); } return m_inv != M; } template inline bool Mod::IsSmallerThan( const INT_TYPE_FOR_MOD& n ) const noexcept { return m_n < Residue( M , n ); } template inline bool Mod::IsBiggerThan( const INT_TYPE_FOR_MOD& n ) const noexcept { return m_n > Residue( M , n ); } template inline bool operator==( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { return n0 == Mod( n1 ); } template inline bool operator==( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return Mod( n0 ) == n0; } template inline bool operator==( const Mod& n0 , const Mod& n1 ) noexcept { return n0.Represent() == n1.Represent(); } template inline bool operator!=( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { return !( n0 == n1 ); } template inline bool operator!=( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return !( n0 == n1 ); } template inline bool operator!=( const Mod& n0 , const Mod& n1 ) noexcept { return !( n0 == n1 ); } template inline bool operator<( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { return n0.IsSmallerThan( n1 ); } template inline bool operator<( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return n1.IsBiggerThan( n0 ); } template inline bool operator<( const Mod& n0 , const Mod& n1 ) noexcept { return n0.Represent() < n1.Represent(); } template inline bool operator<=( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { return !( n1 < n0 ); } template inline bool operator<=( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return !( n1 < n0 ); } template inline bool operator<=( const Mod& n0 , const Mod& n1 ) noexcept { return !( n1 < n0 ); } template inline bool operator>( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { return n1 < n0; } template inline bool operator>( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return n1 < n0; } template inline bool operator>( const Mod& n0 , const Mod& n1 ) noexcept { return n1 < n0; } template inline bool operator>=( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { return !( n0 < n1 ); } template inline bool operator>=( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return !( n0 < n1 ); } template inline bool operator>=( const Mod& n0 , const Mod& n1 ) noexcept { return !( n0 < n1 ); } template Mod operator+( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { auto n = n0; n += n1; return n; } template inline Mod operator+( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return n1 + n0; } template inline Mod operator+( const Mod& n0 , const Mod& n1 ) noexcept { return n0 + n1.Represent(); } template inline Mod operator-( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { return n0 + ( -n1 ); } template inline Mod operator-( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return Mod( n0 - n1.Represent() ); } template inline Mod operator-( const Mod& n0 , const Mod& n1 ) noexcept { return n0 - n1.Represent(); } template Mod operator*( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) noexcept { auto n = n0; n *= n1; return n; } template inline Mod operator*( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) noexcept { return n1 * n0; } template Mod operator*( const Mod& n0 , const Mod& n1 ) noexcept { auto n = n0; n *= n1; return n; } template inline Mod operator/( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) { return n0 / Mod( n1 ); } template inline Mod operator/( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) { return Mod( n0 ) / n1; } template Mod operator/( const Mod& n0 , const Mod& n1 ) { auto n = n0; n /= n1; return n; } template Mod operator%( const Mod& n0 , const INT_TYPE_FOR_MOD& n1 ) { auto n = n0; n %= n1; return n; } template inline Mod operator%( const INT_TYPE_FOR_MOD& n0 , const Mod& n1 ) { return Mod( n0 ) % n1.Represent(); } template inline Mod operator%( const Mod& n0 , const Mod& n1 ) { return n0 % n1.Represent(); } template Mod Inverse( const Mod& n ) { auto n_copy = n; n_copy.Invert(); return n_copy; } template Mod Power( const Mod& n , const INT_TYPE_FOR_MOD& p , const string& method ) { if( p >= 0 ){ return Power,INT_TYPE_FOR_MOD>( n , p , 1 , true , true , method ); } return Inverse( Power( n , -p , method ) ); } template <> inline Mod<2> Power( const Mod<2>& n , const INT_TYPE_FOR_MOD& p , const string& method ) { return p == 0 ? 1 : n; } template inline Mod Power( const Mod& n , const Mod& p , const string& method ) { return Power,INT_TYPE_FOR_MOD>( n , p.Represent() , method ); } template <> inline Mod<2> Power( const Mod<2>& n , const Mod<2>& p , const string& method ) { return p == 0 ? 1 : n; } template <> inline Mod<2> Square >( const Mod<2>& t ) { return t; } void LazyEvaluationOfModularInverse( const INT_TYPE_FOR_MOD& M , const INT_TYPE_FOR_MOD& n , INT_TYPE_FOR_MOD& m ) { static VLArray memory_M{}; // vectorでなくVLArrayだと引数が小さい順に呼び出した時の計算量がO(1)からO(n)に跳ね上がってしまう。 static VLArray > memory_inverse{}; auto itr_M = memory_M.begin() , end_M = memory_M.end(); auto itr_inverse = memory_inverse.begin(); vector* p_inverse = nullptr; while( itr_M != end_M && p_inverse == nullptr ){ if( *itr_M == M ){ p_inverse = &( *itr_inverse ); } itr_M++; itr_inverse++; } if( p_inverse == nullptr ){ memory_M.push_front( M ); memory_inverse.push_front( vector() ); p_inverse = &( memory_inverse.front() ); p_inverse->push_back( M ); } const INT_TYPE_FOR_MOD size = p_inverse->size(); for( INT_TYPE_FOR_MOD i = size ; i <= n ; i++ ){ p_inverse->push_back( 0 ); } INT_TYPE_FOR_MOD& n_inv = ( *p_inverse )[n]; if( n_inv != 0 ){ m = n_inv; return; } const INT_TYPE_FOR_MOD M_abs = M >= 0 ? M : -M; const INT_TYPE_FOR_MOD n_sub = M_abs % n; INT_TYPE_FOR_MOD n_sub_inv = ( *p_inverse )[n_sub]; if( n_sub_inv == 0 ){ LazyEvaluationOfModularInverse( M , n_sub , n_sub_inv ); } if( n_sub_inv != M ){ n_inv = M_abs - ( ( n_sub_inv * ( M_abs / n ) ) % M_abs ); m = n_inv; return; } for( INT_TYPE_FOR_MOD i = 1 ; i < M_abs ; i++ ){ if( ( n * i ) % M_abs == 1 ){ n_inv = i; m = n_inv; return; } } n_inv = M; m = n_inv; return; } // 階乗(INT = Modの時にMでの値が1であることに注意) template inline INT Factorial( const INT& n , const INT& n_min = 1 , const string& mode = "normal" ); // modular階乗(INT1 = Modの時にMでの値が0であることに注意) template inline INT1 ModularFactorial( const INT2& n , const INT2& n_min = 1 , const string& mode = "normal" ); // 再帰式(呼び出し順によっては再帰深度が大きい) template const INT1& ModularFactorialNormalMethod( const INT2& n ); template const INT1& ModularFactorialNormalMethod( const INT2& n , const INT2& n_min ); template const INT1& ModularFactorialNormalMethod_Body( const INT2& n , const INT2& n_min ); // ループ template INT1 ModularFactorialLoopMethod( const INT2& n , const INT2& n_min = 1 ); // modular階乗の逆数(INT1 = Modの時にMでの値がサポート外であることに注意) template inline INT1 ModularFactorialInverse( const INT2& n , const INT2& n_min = 1 , const string& mode = "normal" ); // 再帰式(呼び出し順によっては再帰深度が大きい) template const INT1& ModularFactorialInverseNormalMethod( const INT2& n ); template const INT1& ModularFactorialInverseNormalMethod( const INT2& n , const INT2& n_min ); template const INT1& ModularFactorialInverseNormalMethod_Body( const INT2& n , const INT2& n_min ); // ループ template INT1 ModularFactorialInverseLoopMethod( const INT2& n , const INT2& n_min = 1 ); // 場合の数 template INT Combination( const INT& n , const INT& m , const string& mode = "normal" ); // 再帰式(呼び出し順によっては再帰深度が大きい) template const INT& CombinationNormalMethod( const INT& n , const INT& m ); // ループ(割り算回数が大きい) template INT CombinationLoopMethod( const INT& n , const INT& m ); // 階乗の比(modular演算でない時はオーバーフローしやすい) template inline INT CombinationFactorialNormalMethod( const INT& n , const INT& m ); template inline INT CombinationFactorialLoopMethod( const INT& n , const INT& m ); template inline INT CombinationModularFactorialInverseNormalMethod( const INT& n , const INT& m ); template inline INT CombinationModularFactorialInverseLoopMethod( const INT& n , const INT& m ); template inline INT Factorial( const INT& n , const INT& n_min , const string& mode ) { return ModularFactorial( n , n_min , mode ); } template inline INT1 ModularFactorial( const INT2& n , const INT2& n_min , const string& mode ) { return mode == "loop" ? ModularFactorialLoopMethod( n , n_min ) : ModularFactorialNormalMethod( n , n_min ); } template const INT1& ModularFactorialNormalMethod( const INT2& n ) { // const参照返しなので静的const変数を返す。 if( n < 1 ){ static const INT1 one = 1; return one; } static VLArray memory_n{}; static VLArray memory_answer{}; auto itr_n = memory_n.begin() , end_n = memory_n.end(); auto itr_answer = memory_answer.begin(); while( itr_n != end_n ){ if( *itr_n == n ){ return *itr_answer; } itr_n++; itr_answer++; } const INT1 answer = n * ModularFactorialNormalMethod( n - 1 ); memory_n.push_front( n ); memory_answer.push_front( answer ); return memory_answer.front(); } template const INT1& ModularFactorialNormalMethod( const INT2& n , const INT2& n_min ) { if( n_min == 1 ){ return ModularFactorialNormalMethod( n ); } return ModularFactorialNormalMethod_Body( n , n_min ); } template const INT1& ModularFactorialNormalMethod_Body( const INT2& n , const INT2& n_min ) { // const参照返しなので静的const変数を返す。 if( n < n_min ){ static const INT1 one = 1; return one; } static VLArray memory_n{}; static VLArray > memory_n_min{}; static VLArray > memory_answer{}; VLArray* p_n_min = nullptr; VLArray* p_answer = nullptr; auto itr_n = memory_n.begin() , end_n = memory_n.end(); auto itr_n_min = memory_n_min.begin(); auto itr_answer = memory_answer.begin(); while( itr_n != end_n && p_n_min == nullptr ){ if( *itr_n == n ){ p_n_min = &( *itr_n_min ); p_answer = &( *itr_answer ); } itr_n++; itr_n_min++; itr_answer++; } if( p_n_min == nullptr ){ memory_n.push_front( n ); memory_n_min.push_front( VLArray() ); memory_answer.push_front( VLArray() ); p_n_min = &( memory_n_min.front() ); p_answer = &( memory_answer.front() ); } auto itr_n_min_current = p_n_min->begin() , end_n_min_current = p_n_min->end(); auto itr_answer_current = p_answer->begin(); while( itr_n_min_current != end_n_min_current ){ if( *itr_n_min_current == n_min ){ return *itr_answer_current; } itr_n_min_current++; itr_answer_current++; } const INT1 answer = ModularFactorialNormalMethod( n , n_min + 1 ) * n_min; p_n_min->push_front( n_min ); p_answer->push_front( answer ); return p_answer->front(); } template INT1 ModularFactorialLoopMethod( const INT2& n , const INT2& n_min ) { INT1 f = 1; for( INT2 i = n_min ; i <= n ; i++ ){ f *= i; } return f; } template inline INT1 ModularFactorialInverse( const INT2& n , const INT2& n_min , const string& mode ) { return mode == "loop" ? ModularFactorialInverseLoopMethod( n , n_min ) : ModularFactorialInverseNormalMethod( n , n_min ); } template const INT1& ModularFactorialInverseNormalMethod( const INT2& n ) { // const参照返しなので静的const変数を返す。 if( n < 1 ){ static const INT1 one = 1; return one; } static VLArray memory_n{}; static VLArray memory_answer{}; auto itr_n = memory_n.begin() , end_n = memory_n.end(); auto itr_answer = memory_answer.begin(); while( itr_n != end_n ){ if( *itr_n == n ){ return *itr_answer; } itr_n++; itr_answer++; } const INT1 answer = ModularFactorialInverseNormalMethod( n - 1 ) / n; memory_n.push_front( n ); memory_answer.push_front( answer ); return memory_answer.front(); } template const INT1& ModularFactorialInverseNormalMethod( const INT2& n , const INT2& n_min ) { if( n_min == 1 ){ return ModularFactorialInverseNormalMethod( n ); } return ModularFactorialInverseNormalMethod_Body( n , n_min ); } template const INT1& ModularFactorialInverseNormalMethod_Body( const INT2& n , const INT2& n_min ) { // const参照返しなので静的const変数を返す。 if( n < n_min ){ static const INT1 one = 1; return one; } static VLArray memory_n{}; static VLArray > memory_n_min{}; static VLArray > memory_answer{}; VLArray* p_n_min = nullptr; VLArray* p_answer = nullptr; auto itr_n = memory_n.begin() , end_n = memory_n.end(); auto itr_n_min = memory_n_min.begin(); auto itr_answer = memory_answer.begin(); while( itr_n != end_n && p_n_min == nullptr ){ if( *itr_n == n ){ p_n_min = &( *itr_n_min ); p_answer = &( *itr_answer ); } itr_n++; itr_n_min++; itr_answer++; } if( p_n_min == nullptr ){ memory_n.push_front( n ); memory_n_min.push_front( VLArray() ); memory_answer.push_front( VLArray() ); p_n_min = &( memory_n_min.front() ); p_answer = &( memory_answer.front() ); } auto itr_n_min_current = p_n_min->begin() , end_n_min_current = p_n_min->end(); auto itr_answer_current = p_answer->begin(); while( itr_n_min_current != end_n_min_current ){ if( *itr_n_min_current == n_min ){ return *itr_answer_current; } itr_n_min_current++; itr_answer_current++; } const INT1 answer = ModularFactorialInverseNormalMethod( n , n_min + 1 ) / (INT1)n_min; p_n_min->push_front( n_min ); p_answer->push_front( answer ); return p_answer->front(); } template INT1 ModularFactorialInverseLoopMethod( const INT2& n , const INT2& n_min ) { INT1 f = 1; for( INT2 i = n_min ; i <= n ; i++ ){ f /= i; } return f; } template INT Combination( const INT& n , const INT& m , const string& mode ) { if( n < m ){ return 0; } if( mode == "loop" ){ return CombinationLoopMethod( n , m ); } if( mode == "factorial normal" ){ return CombinationFactorialNormalMethod( n , m ); } if( mode == "factorial loop" ){ return CombinationFactorialLoopMethod( n , m ); } if( mode == "modular factorial inverse normal" ){ return CombinationModularFactorialInverseNormalMethod( n , m ); } if( mode == "modular factorial inverse loop" ){ return CombinationModularFactorialInverseLoopMethod( n , m ); } return CombinationNormalMethod( n , m ); } template const INT& CombinationNormalMethod( const INT& n , const INT& m ) { // const参照返しなので静的const変数を返す。 if( m == 0 ){ static const INT one = 1; return one; } static VLArray memory_n{}; static VLArray > memory_m{}; static VLArray > memory_answer{}; VLArray* p_m = nullptr; VLArray* p_answer = nullptr; auto itr_n = memory_n.begin() , end_n = memory_n.end(); auto itr_m = memory_m.begin(); auto itr_answer = memory_answer.begin(); while( itr_n != end_n && p_m == nullptr ){ if( *itr_n == n ){ p_m = &( *itr_m ); p_answer = &( *itr_answer ); } itr_n++; itr_m++; itr_answer++; } if( p_m == nullptr ){ memory_n.push_front( n ); memory_m.push_front( VLArray() ); memory_answer.push_front( VLArray() ); p_m = &( memory_m.front() ); p_answer = &( memory_answer.front() ); } const INT size = p_m->size(); // p_mには{...,3,2,1}と入っていくのでm <= sizeの時にmが見付かる。 if( m <= size ){ auto itr_m_current = p_m->begin() , end_m_current = p_m->end(); auto itr_answer_current = p_answer->begin(); while( itr_m_current != end_m_current ){ if( *itr_m_current == m ){ return *itr_answer_current; } itr_m_current++; itr_answer_current++; } } const INT answer = ( CombinationNormalMethod( n , m - 1 ) * ( n - m + 1 ) ) / m; p_m->push_front( m ); p_answer->push_front( answer ); return p_answer->front(); } template INT CombinationLoopMethod( const INT& n , const INT& m ) { const INT m_comp = n - m; const INT m_copy = m_comp < m ? m_comp : m; INT answer = 1; for( INT i = 0 ; i < m_copy ; i++ ){ answer *= ( n - i ); answer /= i + 1; } return answer; } template inline INT CombinationFactorialNormalMethod( const INT& n , const INT& m ) { return Factorial( n , n - m + 1 , "normal" ) / Factorial( m , 1 , "normal" ); } template inline INT CombinationFactorialLoopMethod( const INT& n , const INT& m ) { return Factorial( n , n - m + 1 , "loop" ) / Factorial( m , 1 , "loop" ); } template inline INT CombinationModularFactorialInverseNormalMethod( const INT& n , const INT& m ) { return Factorial( n , n - m + 1 , "normal" ) * ModularFactorialInverse( m , 1 , "normal" ); } template inline INT CombinationModularFactorialInverseLoopMethod( const INT& n , const INT& m ) { return Factorial( n , n - m + 1 , "loop" ) * ModularFactorialInverse( m , 1 , "loop" ); } constexpr const ll P = 998244353; int main(){ CIN( ll , N ); CIN( ll , K ); // S = sum_{i=1}^{N} S(i) e_i = sum_{i=1}^{N} S(i) (e_i - e_1) // = sum_{i=1}^{N} S(i) sum_{j=1}^{i-1} b_j // = sum_{j=1}^{N} ( ( sum_{i=j+1}^{N} S(i) ) % 2 ) b_j // f(S) = sum_{j=1}^{N} ( sum_{i=j+1}^{N} S(i) ) % 2 // = Sの1のうち右から数えて奇数番目のものの左に続く0の個数+1の総和 // #{S|f(S) = d} = N個のうち左端以外からd個選ぶ方法の総数 = C( N - 1 , d ) // answer = sum_{d=0}^{N-1} C(N-1,d) d^K; ll N_minus = N - 1; const string mode_comb = "normal"; const string mode_pow = "binary"; Mod

answer{ 0 }; FOR_LL( d , 0 , N ){ answer += Combination >( N_minus , d , mode_comb ) * Power,ll>( Mod

( d ) , K , 1 , true , mode_pow ); } RETURN( answer.Represent() ); }