結果

問題 No.2584 The University of Tree
ユーザー 👑 p-adicp-adic
提出日時 2023-12-12 22:36:29
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 995 ms / 3,000 ms
コード長 52,387 bytes
コンパイル時間 4,179 ms
コンパイル使用メモリ 259,536 KB
実行使用メモリ 149,392 KB
最終ジャッジ日時 2023-12-12 22:37:05
合計ジャッジ時間 26,439 ms
ジャッジサーバーID
(参考情報)
judge12 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 4 ms
7,168 KB
testcase_01 AC 4 ms
7,168 KB
testcase_02 AC 4 ms
7,168 KB
testcase_03 AC 4 ms
7,168 KB
testcase_04 AC 4 ms
7,296 KB
testcase_05 AC 4 ms
7,296 KB
testcase_06 AC 5 ms
7,296 KB
testcase_07 AC 5 ms
7,296 KB
testcase_08 AC 4 ms
7,296 KB
testcase_09 AC 4 ms
7,296 KB
testcase_10 AC 4 ms
7,296 KB
testcase_11 AC 4 ms
7,296 KB
testcase_12 AC 4 ms
7,296 KB
testcase_13 AC 4 ms
7,296 KB
testcase_14 AC 4 ms
7,296 KB
testcase_15 AC 4 ms
7,296 KB
testcase_16 AC 4 ms
7,296 KB
testcase_17 AC 4 ms
7,296 KB
testcase_18 AC 4 ms
7,296 KB
testcase_19 AC 4 ms
7,296 KB
testcase_20 AC 4 ms
7,296 KB
testcase_21 AC 4 ms
7,296 KB
testcase_22 AC 380 ms
78,924 KB
testcase_23 AC 475 ms
93,372 KB
testcase_24 AC 286 ms
59,004 KB
testcase_25 AC 339 ms
67,588 KB
testcase_26 AC 203 ms
47,732 KB
testcase_27 AC 449 ms
79,244 KB
testcase_28 AC 243 ms
46,556 KB
testcase_29 AC 110 ms
28,544 KB
testcase_30 AC 993 ms
144,404 KB
testcase_31 AC 938 ms
146,080 KB
testcase_32 AC 172 ms
39,224 KB
testcase_33 AC 344 ms
146,708 KB
testcase_34 AC 103 ms
40,348 KB
testcase_35 AC 981 ms
149,392 KB
testcase_36 AC 922 ms
149,228 KB
testcase_37 AC 953 ms
146,264 KB
testcase_38 AC 913 ms
145,224 KB
testcase_39 AC 941 ms
149,092 KB
testcase_40 AC 995 ms
149,168 KB
testcase_41 AC 948 ms
149,172 KB
testcase_42 AC 969 ms
146,264 KB
testcase_43 AC 949 ms
145,220 KB
testcase_44 AC 871 ms
149,392 KB
testcase_45 AC 898 ms
149,392 KB
testcase_46 AC 349 ms
149,392 KB
testcase_47 AC 496 ms
149,100 KB
testcase_48 AC 253 ms
60,484 KB
testcase_49 AC 684 ms
134,276 KB
testcase_50 AC 530 ms
110,968 KB
testcase_51 AC 294 ms
66,372 KB
testcase_52 AC 129 ms
34,560 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#ifdef INCLUDE_MAIN

inline void Solve()
{
  // // 数
  DEXPR( ll , bound_N , 200000 , 100 ); // 0が5個
  // // // DEXPR( ll , bound_N , 1000000000 , 100 ); // 0が9個
  // // // DEXPR( ll , bound_N , 1000000000000000000 , 100 ); // 0が18個
  // // CEXPR( TYPE_OF( bound_N ) , bound_M , bound_N );
  CIN( int , N );
  // // CIN_ASSERT( N , 1 , bound_N ); // ランダムテスト用。
  // ll answer = 0;
  // // MP answer = 0;
  // RETURN( answer );

  // // 配列
  // CIN_A( ll , A , N ); CIN_A( ll , B , N );
  // // CIN_A( MP , A , N );  CIN_A( MP , B , N );
  // // vector<ll> A( N ) , B( N );
  // // vector<MP> A( N ) , B( N );
  // // ll A[bound_N] , ll B[bound_N]; // 関数の引数に使う。
  // // MP A[bound_N] , MP B[bound_N]; // 関数の引数に使う。
  // // FOR( i , 0 , N ){ cin >> A[i] >> B[i]; }
  // // FOR( i , 0 , N * 2 ){ cin >> ( i < N ? A[i] : B[i-N] ); }
  // ll answer = 0;
  // // MP answer = 0;
  // // COUT_A( A , N );
  // RETURN( answer );

  // // 文字列
  // CIN( string , S , T );
  // ll answer = 0;
  // // MP answer = 0;
  // RETURN( answer );

  // // 順列
  // vector<int> A( N ) , A_inv( N );
  // FOR( i , 0 , N ){ cin >> A[i]; A_inv[--A[i]] = i; }
  // ll answer = 0;
  // // MP answer = 0;
  // // COUT( answer );
  // RETURN( answer );
  
  // グラフ
  e<int>.resize( N * 2 );
  // e<path>.resize( N );
  ll M = N - 1;
  set<T2<int>> E_set[M];
  unordered_map<int,int> E_num[N];
  FOR( i , 0 , N ){
    CIN( int , Ci );
    FOREQ( k , 1 , Ci ){
      CIN( int , Eik );
      E_set[--Eik].insert( { i , k } );
    }
  }
  FOR( j , 0 , M ){
    // CIN_ASSERT( uj , 1 , N ); CIN_ASSERT( vj , 1 , N );
    // uj--; vj--;
    auto itr = E_set[j].begin();
    auto& [uj,ku] = *( itr++ ); auto& [vj,kv] = *itr;
    e<int>[uj].push_back( vj ); e<int>[vj].push_back( uj );
    // 分岐番号を格納。分岐0は拠点。
    E_num[uj][vj] = ku;
    E_num[vj][uj] = kv;
    // CIN( ll , wj );
    // e<path>[uj].push_back( { vj , wj } ); e<path>[vj].push_back( { uj , wj } );
  }
  DepthFirstSearchOnTree<bound_N*2,E<int> > dfst{ N , 0 };

  dfst.SetChildren();

  // value[i][m] = iの分岐mから子ノードへ動く時の総和
  vector<MP> value[N] = {};
  // left_sum[i][m] = iの分岐mからiの分岐0,...,m-1のうち子ノードであるものへ動く時の総和
  vector<MP> left_sum[N];
  // right_sum[i][m] = iの分岐mからiの分岐m+1,...,size_i-1のうち子ノードであるものへ動く時の総和
  vector<MP> right_sum[N];

  for( int i = 0 ; i < N ; i++ ){

    // 拠点と親ノードも含めるので+2する。
    value[i].resize( dfst.m_children[i].size() + 1 + ( i == 0 ? 0 : 1 ) );

  }

  for( int n = 0 ; n < N ; n++ ){
    
    const int& i = dfst.NodeNumber( n , true );
    const int size_i = value[i].size();
    value[i][0] = 1;
    MP temp = 0;
    MP power = PW( MP( i + 1 ) , size_i - 1 );
    MP inv = MP::Inverse( i + 1 );
    left_sum[i].resize( size_i );

    for( int m = 1 ; m < size_i ; m++ ){

      temp = temp * inv + value[i][m-1] * power;
      left_sum[i][m] = temp;

    }

    temp = 0;
    right_sum[i].resize( size_i );

    for( int m = size_i - 2 ; m >= 0 ; m-- ){

      temp = ( temp + value[i][m+1] ) * ( i + 1 );
      right_sum[i][m] = temp;

    }

    const int& j = dfst.Parent( i );

    if( j != -1 ){

      value[j][E_num[j][i]] = left_sum[i][E_num[i][j]] + right_sum[i][E_num[i][j]];

    }
    
  }

  // left_sum[i][m] = iの分岐mからiの分岐0,...,m-1のうち子ノードであるものへ動く時の総和
  // right_sum[i][m] = iの分岐mからiの分岐m+1,...,size_i-1のうち子ノードであるものへ動く時の総和
  // だったがこれらに親ノードの寄与を追加し
  // left_sum[i][m] = iの分岐mからiの分岐0,...,m-1へ動く時の総和
  // right_sum[i][m] = iの分岐mからiの分岐m+1,...,size_i-1へ動く時の総和
  // とする。
  for( int n = 1 ; n < N ; n++ ){
    
    const int& i = dfst.NodeNumber( n );
    const int& j = dfst.Parent( i );
    const int size_i = value[i].size();

    // jの分岐E_num[j][i]はj->iの始点に対応するjの分岐
    // jの分岐E_num[j][i]からjの分岐E_num[j][i]以外の分岐へ動く時の総和
    const MP rest_i = left_sum[j][E_num[j][i]] + right_sum[j][E_num[j][i]];
    
    for( int m = 0 ; m < E_num[i][j] ; m++ ){

      right_sum[i][m] += rest_i * PW( MP( i + 1 ) , ( E_num[i][j] - m ) % size_i );

    }

    for( int m = E_num[i][j] + 1 ; m < size_i ; m++ ){

      left_sum[i][m] += rest_i * PW( MP( i + 1 ) , E_num[i][j] + size_i - m );

    }

  }

  for( int i = 0 ; i < N ; i++ ){

    // right_sum[i][0] = 拠点iから分岐1,...,size_i-1へ動く時の総和
    COUT( right_sum[i][0] );

  }

  // ll answer = 0;
  // MP answer = 0;
  // RETURN( answer );

  // // 座標圧縮や単一クエリタイプなどのための入力格納
  // vector<T3<ll> > data( M );
  // FOR( j , 0 , M ){ CIN( ll , x , y , z ); data[j] = { x , y , z }; }
  // ll answer = 0;
  // // MP answer = 0;
  // RETURN( answer );
  
  // // 一般のクエリ
  // CIN( int , Q );
  // // DEXPR( int , bound_Q , 100000 , 100 ); // 基本不要。
  // // CIN_ASSERT( Q , 1 , bound_Q ); // 基本不要。
  // // vector<T3<int> > query( Q );
  // // vector<T2<int> > query( Q );
  // FOR( q , 0 , Q ){
  //   CIN( int , type );
  //   if( type == 1 ){
  //     CIN( int , x , y );
  //     // query[q] = { type , x , y };
  //   } else if( type == 2 ){
  //     CIN( int , x , y );
  //     // query[q] = { type , x , y };
  //     COUT( x + y );
  //   }
  //   // CIN( int , x , y );
  //   // // query[q] = { x , y };
  //   // COUT( x + y );
  // }
  // // sort( query , query + Q );
  // // FOR( q , 0 , Q ){
  // //   auto& [x,y] = query[q];
  // //   // auto& [type,x,y] = query[q];
  // // }
  // ll answer = 0;
  // // MP answer = 0;
  // RETURN( answer );
  
  // // グリッド
  // // DEXPR( int , bound_H , 2000 , 30 );
  // // // DEXPR( int , bound_H , 100000 , 10 ); // 0が5個
  // // // CEXPR( int , bound_H , 1000000000 ); // 0が9個
  // // CEXPR( int , bound_W , bound_H );
  // // static_assert( ll( bound_H ) * bound_W < ll( 1 ) << 31 );
  // // CEXPR( int , bound_HW , bound_H * bound_W );
  // cin >> H >> W;
  // // SET_ASSERT( H , 1 , bound_H ); SET_ASSERT( W , 1 , bound_W ); // ランダムテスト用。  // H_minus = H - 1; W_minus = W - 1; HW = H * W;
  // vector<string> S( H );
  // FOR( i , 0 , H ){
  //   cin >> S[i];
  //   // SetEdgeOnGrid( S[i] , i , e<int> );
  //   // SetWallOnGrid( S[i] , i , non_wall );
  // }
  // // {h,w}へデコード: EnumHW( v )
  // // {h,w}をコード: EnumHW_inv( h , w );
  // // (i,j)->(k,h)の方向番号を取得: DirectionNumberOnGrid( i , j , k , h );
  // // v->wの方向番号を取得: DirectionNumberOnGrid( v , w );
  // // 方向番号の反転U<->D、R<->L: ReverseDirectionNumberOnGrid( n );
  // ll answer = 0;
  // // MP answer = 0;
  // RETURN( answer );
}
REPEAT_MAIN(1);

#else // INCLUDE_MAIN

#ifdef INCLUDE_SUB

template <typename PATH> list<PATH> E( const int& i )
{
  // list<PATH> answer{};
  list<PATH> answer = e<PATH>[i];
  // VVV 入力によらない処理は以下に挿入する。

  // AAA 入力によらない処理は以上に挿入する。
  return answer;
}

template <typename T> inline T F( const T& t ){ return f<T>[t]; }
template <typename T> inline T G( const int& i ){ return g<T>[i]; }

// COMPAREに使用。圧縮時は削除する。
ll Naive( int N , int M , int K )
{
  ll answer = N + M + K;
  return answer;
}

// COMPAREに使用。圧縮時は削除する。
ll Answer( ll N , ll M , ll K )
{
  // START_WATCH;
  ll answer = N + M + K;

  // // TLに準じる乱択や全探索。デフォルトの猶予は100.0[ms]。
  // CEXPR( double , TL , 2000.0 );
  // while( CHECK_WATCH( TL ) ){

  // }
  return answer;
}

// 圧縮時は中身だけ削除する。
inline void Experiment()
{
  // CEXPR( int , bound , 10 );
  // FOREQ( N , 0 , bound ){
  //   FOREQ( M , 0 , bound ){
  //     FOREQ( K , 0 , bound ){
  //   	COUT( N , M , K , ":" , Naive( N , M , K ) );
  //     }
  //   }
  //   // cout << Naive( N ) << ",\n"[N==bound];
  // }
}

// 圧縮時は中身だけ削除する。
inline void SmallTest()
{
  // CEXPR( int , bound , 10 );
  // FOREQ( N , 0 , bound ){
  //   FOREQ( M , 0 , bound ){
  //     FOREQ( K , 0 , bound ){
  //   	COMPARE( N , M , K );
  //     }
  //   }
  //   // COMPARE( N );
  // }
}

#define INCLUDE_MAIN
#include __FILE__

#else // INCLUDE_SUB

#ifdef INCLUDE_LIBRARY

/*

C-x 3 C-x o C-x C-fによるファイル操作用

BFS:
c:/Users/user/Documents/Programming/Mathematics/Geometry/Graph/BreadthFirstSearch/compress.txt

CoordinateCompress:
c:/Users/user/Documents/Programming/Mathematics/SetTheory/DirectProduct/CoordinateCompress/compress.txt

DFSOnTree
c:/Users/user/Documents/Programming/Mathematics/Geometry/Graph/DepthFirstSearch/Tree/a.hpp

Divisor:
c:/Users/user/Documents/Programming/Mathematics/Arithmetic/Prime/Divisor/compress.txt

Polynomial
c:/Users/user/Documents/Programming/Mathematics/Polynomial/compress.txt

UnionFind
c:/Users/user/Documents/Programming/Utility/VLTree/UnionFindForest/compress.txt

*/

// VVV 常設でないライブラリは以下に挿入する。

#define DC_OF_FIRST_SEARCH(BREADTH)TE <int V_max> CL BREADTH ## FirstSearch_Body{PU:int m_V;int m_init;LI<int> m_next;bool m_found[V_max];int m_prev[V_max];IN BREADTH ## FirstSearch_Body(CRI V);IN BREADTH ## FirstSearch_Body(CRI V,CRI init);IN VO Reset(CRI init);IN VO Shift(CRI init);IN CRI SZ()CO;IN CRI init()CO;IN bool& found(CRI i);IN CRI prev(CRI i)CO;int Next();virtual LI<int> e(CRI t)= 0;};TE <int V_max,LI<int> E(CRI)> CL BREADTH ## FirstSearch:PU BREADTH ## FirstSearch_Body<V_max>{PU:TE<TY... Args> IN BREADTH ## FirstSearch(CO Args&... args);IN LI<int> e(CRI t);};TE <int V_max,LI<int> E(CRI)> VO BREADTH ## FirstConnectedComponent(CRI V,int(&vertex)[V_max],int& count);
#define DF_OF_FIRST_SEARCH(BREADTH,PUSH)TE <int V_max> IN BREADTH ## FirstSearch_Body<V_max>::BREADTH ## FirstSearch_Body(CRI V):m_V(V),m_init(),m_next(),m_found(),m_prev(){assert(m_V <= V_max);for(int i = 0;i < m_V;i++){m_prev[i] = -1;}}TE <int V_max> IN BREADTH ## FirstSearch_Body<V_max>::BREADTH ## FirstSearch_Body(CRI V,CRI init):BREADTH ## FirstSearch_Body(V){m_init = init;m_next.push_back(m_init);m_found[m_init] = true;}TE <int V_max,LI<int> E(CRI)> TE <TY... Args> IN BREADTH ## FirstSearch<V_max,E>::BREADTH ## FirstSearch(CO Args&... args):BREADTH ## FirstSearch_Body<V_max>(args...){}TE <int V_max> IN VO BREADTH ## FirstSearch_Body<V_max>::Reset(CRI init){m_init = init;assert(m_init < m_V);m_next.clear();m_next.push_back(m_init);for(int i = 0;i < m_V;i++){m_found[i] = i == m_init;m_prev[i] = -1;}}TE <int V_max> IN VO BREADTH ## FirstSearch_Body<V_max>::Shift(CRI init){m_init = init;assert(m_init < m_V);m_next.clear();if(! m_found[m_init]){m_next.push_back(m_init);m_found[m_init] = true;}}TE <int V_max> IN CRI BREADTH ## FirstSearch_Body<V_max>::SZ()CO{RE m_V;}TE <int V_max> IN CRI BREADTH ## FirstSearch_Body<V_max>::init()CO{RE m_init;}TE <int V_max> IN bool& BREADTH ## FirstSearch_Body<V_max>::found(CRI i){assert(i < m_V);RE m_found[i];}TE <int V_max> IN CRI BREADTH ## FirstSearch_Body<V_max>::prev(CRI i)CO{assert(i < m_V);RE m_prev[i];}TE <int V_max> int BREADTH ## FirstSearch_Body<V_max>::Next(){if(m_next.empty()){RE -1;}CO int i_curr = m_next.front();m_next.pop_front();LI<int> edge = e(i_curr);WH(! edge.empty()){CRI i = edge.front();bool& found_i = m_found[i];if(! found_i){m_next.PUSH(i);m_prev[i] = i_curr;found_i = true;}edge.pop_front();}RE i_curr;}TE <int V_max,LI<int> E(CRI)> IN LI <int> BREADTH ## FirstSearch<V_max,E>::e(CRI t){RE E(t);}TE <int V_max,LI<int> E(CRI)> VO BREADTH ## FirstConnectedComponentSearch(CRI V,int(&vertex)[V_max],int& count){BREADTH ## FirstSearch<V_max,E> bfs{V};count = 0;for(int i = 0;i < V;i++){vertex[i] = -1;}for(int i = 0;i < V;i++){if(vertex[i] == -1){bfs.Shift(i);int j = bfs.Next();WH(j != -1?vertex[j] == 0:false){vertex[j] = count;j = bfs.Next();}count++;}}RE;}
DC_OF_FIRST_SEARCH(Depth);DF_OF_FIRST_SEARCH(Depth,push_front);

// digitはAncestorとLCAにのみ使用。普段は0で良い。
// 2^16 = 65536
// 2^17 = 131072
// 2^18 = 262144
template <int V_max,list<int> E(const int&),int digit = 0>
class DepthFirstSearchOnTree :
  public DepthFirstSearch<V_max,E>
{

// private:
public:
  int m_reversed[V_max];

  vector<vector<int> > m_children;
  vector<int> m_children_num;
  bool m_set_children;

  vector<int> m_depth;
  bool m_set_depth;

  vector<int> m_height;
  bool m_set_height;

  vector<int> m_weight;
  bool m_set_weight;

  vector<int> m_doubling[digit];
  bool m_set_doubling;

public:
  inline DepthFirstSearchOnTree( const int& V , const int& root );
  inline void Reset( const int& init ) = delete;
  inline void Shift( const int& init ) = delete;

  inline const int& Root() const;
  inline const int& Parent( const int& i ) const;
  inline const vector<int>& Children( const int& i );
  inline const int& Depth( const int& i ) const;
  inline const int& Height( const int& i );
  inline const int& Weight( const int& i );

  // 探索順にノードを番号づける。
  inline const int& NodeNumber( const int& i , const bool& reversed = false ) const;
  // 共通の親を持つノード間で昇順に番号づける。
  inline const int& ChildrenNumber( const int& i );  

  // 各ノードの高さ < 2^digitの場合のみサポート。
  // n階の親Parent^n( i )を返す。
  int Ancestor( int i , int n );
  int LCA( int i , int j );
  // LCAからi,j側に進める場合に進んだ先の頂点のラベルをi_prev,j_prevに格納する。
  int LCA( int i , int j , int& i_prev , int& j_prev );

  // 入力の範囲内で要件
  // (2) 任意の非負整数n,iとTの要素のみからなる任意の長さnの任意の列(t1,...,tn)と
  //     その並び換え(s1,...,sn)に対しf((t1,...,tn),i)=f((s1,...,sn),i)である。
  // を満たす場合のみサポート。
  // dp[j] = f(jの子ノードkを渡るdp[k]の列,j)
  // を満たす配列dpの根での値dp[m_init]をO(m_V)で求める。
  template <typename T , T f(const list<T>&,const int&)> T RootingDP();

  // (T,m_T:T^2->T,e_T:1->T)が入力の範囲内で要件
  // (1) (T,m_T:T^2->T,e_T:1->T)がモノイドである
  // (2) 任意の非負整数n,iとTの要素のみからなる任意の長さnの任意の列(t1,...,tn)と
  //     その並び換え(s1,...,sn)に対し
  //     f(m_T(...m_T(t1,t2),...tn),j)=f(m_T(...m_T(s1,s2),...sn),j)である。
  // を満たす場合のみサポート。
  // dp[i][j] = f(iを根とみなした時のjの子ノードkを渡るg(dp[i][k],jはiの子孫,j,k)のm_Tに関する積,j)
  // を満たす二重配列dpの対角成分dp[i][i]をO(m_V)で求めてdに格納する。
  template <typename T , T m_T(const T&,const T&) ,const T& e_T() , T f(const T&,const int&), T g(const T&,const bool&,const int&,const int&)> void RerootingDP( T ( &d )[V_max] );
  // fはノードjごとのデータ、gは有向辺b?(j,k):(k,j)ごとのデータに対応。

// private:
public:
  void SetChildren();
  void SetDepth();
  void SetHeight();
  void SetWeight();

  // 各ノードの高さ < 2^digitの場合のみサポート。
  // LCA()を呼ぶ前にAncestor()経由で完全にダブリングを設定するため、
  // 遅延評価する../../../../Mathematics/Function/Iteration/Doubling/のダブリングで代用しない。
  void SetDoubling();

};

template <int V_max,list<int> E(const int&),int digit> inline DepthFirstSearchOnTree<V_max,E,digit>::DepthFirstSearchOnTree( const int& V , const int& root ) :
  DepthFirstSearch<V_max,E>( V , root ) , m_reversed() , m_children() , m_set_children() , m_depth() , m_set_depth() , m_height() , m_set_height() , m_weight() , m_set_weight() , m_doubling() , m_set_doubling()
{

  int n = DepthFirstSearch<V_max,E>::size();
  
  while( --n >= 0 ){
    
    m_reversed[n] = DepthFirstSearch<V_max,E>::Next();

  }

}

template <int V_max,list<int> E(const int&),int digit> inline const int& DepthFirstSearchOnTree<V_max,E,digit>::Root() const { return DepthFirstSearch<V_max,E>::init(); }

template <int V_max,list<int> E(const int&),int digit> inline const int& DepthFirstSearchOnTree<V_max,E,digit>::Parent( const int& i ) const { return DepthFirstSearch<V_max,E>::prev( i ); }
template <int V_max,list<int> E(const int&),int digit> inline const vector<int>& DepthFirstSearchOnTree<V_max,E,digit>::Children( const int& i ) { if( ! m_set_children ){ SetChildren(); } return m_children[i]; }
template <int V_max,list<int> E(const int&),int digit> inline const int& DepthFirstSearchOnTree<V_max,E,digit>::Depth( const int& i ) const { if( ! m_set_depth ){ SetDepth(); } return m_depth[i]; }
template <int V_max,list<int> E(const int&),int digit> inline const int& DepthFirstSearchOnTree<V_max,E,digit>::Height( const int& i ) { if( ! m_set_height ){ SetHeight(); } return m_height[i]; }
template <int V_max,list<int> E(const int&),int digit> inline const int& DepthFirstSearchOnTree<V_max,E,digit>::Weight( const int& i ) { if( ! m_set_weight ){ SetWeight(); } return m_weight[i]; }

template <int V_max,list<int> E(const int&),int digit> inline const int& DepthFirstSearchOnTree<V_max,E,digit>::NodeNumber( const int& i , const bool& reversed ) const { return m_reversed[reversed ? i : DepthFirstSearch<V_max,E>::size() - 1 - i]; }
template <int V_max,list<int> E(const int&),int digit> inline const int& DepthFirstSearchOnTree<V_max,E,digit>::ChildrenNumber( const int& i ) { if( ! m_set_children ){ SetChildren(); } return m_children_num[i]; }

template <int V_max,list<int> E(const int&),int digit>
int DepthFirstSearchOnTree<V_max,E,digit>::Ancestor( int i , int n )
{

  if( ! m_set_doubling ){

    SetDoubling();

  }

  assert( ( n >> digit ) == 0 );
    
  int d = 0;
  
  while( n != 0 ){

    if( ( n & 1 ) == 1 ){

      assert( ( i = m_doubling[d][i] ) != -1 );

    }
    
    d++;
    n >>= 1;

  }

  return i;

}

template <int V_max,list<int> E(const int&),int digit>
int DepthFirstSearchOnTree<V_max,E,digit>::LCA( int i , int j )
{

  int diff = Depth( i ) - Depth( j );

  if( diff < 0 ){

    swap( i , j );
    diff *= -1;

  }
    
  i = Ancestor( i , diff );

  if( i == j ){

    return i;
      
  }
    
  int d = digit;

  while( --d >= 0 ){

    const int ( &doubling_d )[V_max] = m_doubling[d];
    const int& doubling_d_i = doubling_d[i];
    const int& doubling_d_j = doubling_d[j];

    if( doubling_d_i != doubling_d_j ){

      i = doubling_d_i;
      j = doubling_d_j;
      assert( i != -1 );
      assert( j != -1 );

    }

  }

  return Parent( i );

}

template <int V_max,list<int> E(const int&),int digit>
int DepthFirstSearchOnTree<V_max,E,digit>::LCA( int i , int j , int& i_prev , int& j_prev )
{

  if( i == j ){

    i_prev = j_prev = -1;
    return i;

  }
  
  int diff = Depth( i ) - Depth( j );

  if( diff < 0 ){

    return LCA( j , i , j_prev , i_prev );

  }
  
  if( diff > 0 ){

    i_prev = Ancestor( i , diff - 1 );
    i = Parent( i_prev );
    assert( i != -1 );
    
    if( i == j ){

      j_prev = -1;
      return i;
      
    }
    
  } else if( ! m_set_doubling ){

    SetDoubling();

  }
    
  int d = digit;

  while( --d >= 0 ){

    const int ( &doubling_d )[V_max] = m_doubling[d];
    const int& doubling_d_i = doubling_d[i];
    const int& doubling_d_j = doubling_d[j];

    if( doubling_d_i != doubling_d_j ){

      i = doubling_d_i;
      j = doubling_d_j;
      assert( i != -1 );
      assert( j != -1 );

    }

  }

  i_prev = i;
  j_prev = j;
  return Parent( i_prev );

}

template <int V_max,list<int> E(const int&),int digit>
void DepthFirstSearchOnTree<V_max,E,digit>::SetChildren()
{

  assert( !m_set_children );
  m_set_children = true;
  const int& V = DepthFirstSearch<V_max,E>::size();
  m_children.resize( V );
  m_children_num.resize( V );
  
  for( int i = 0 ; i < V ; i++ ){

    const int& j = Parent( i );

    if( j == -1 ){

      m_children_num[i] = -1;

    } else {
      
      vector<int>& m_children_j = m_children[j];
      m_children_num[i] = m_children_j.size();
      m_children_j.push_back( i );

    }

  }

  return;
  
}

template <int V_max,list<int> E(const int&),int digit>
void DepthFirstSearchOnTree<V_max,E,digit>::SetDepth()
{

  assert( !m_set_depth );
  m_set_depth = true;
  const int& V = DepthFirstSearch<V_max,E>::size();
  m_depth.resize( V );
  
  for( int i = 0 ; i < V ; i++ ){

    const int& reversed_i = m_reversed[i];
    const int& parent_i = Parent( reversed_i );

    if( parent_i != -1 ){

      m_depth[i] += m_depth[parent_i] + 1;

    }

  }

  return;

}

template <int V_max,list<int> E(const int&),int digit>
void DepthFirstSearchOnTree<V_max,E,digit>::SetHeight()
{

  assert( !m_set_height );
  m_set_height = true;
  const int& V = DepthFirstSearch<V_max,E>::size();
  m_height.resize( V );
  
  for( int i = 0 ; i < V ; i++ ){

    const int& reversed_i = m_reversed[i];
    const int& parent_i = Parent( reversed_i );

    if( parent_i != -1 ){

      int& height_parent_i = m_height[parent_i];
      const int& height_i = m_height[reversed_i];
      height_parent_i > height_i ? height_parent_i : height_parent_i = height_i + 1;

    }

  }

  return;

}

template <int V_max,list<int> E(const int&),int digit>
void DepthFirstSearchOnTree<V_max,E,digit>::SetWeight()
{

  assert( !m_set_weight );
  m_set_weight = true;
  const int& V = DepthFirstSearch<V_max,E>::size();
  m_weight.resize( V );
  
  for( int i = 0 ; i < V ; i++ ){

    const int& reversed_i = m_reversed[i];
    const int& parent_i = Parent( reversed_i );

    if( parent_i != -1 ){

      m_weight[parent_i] += m_weight[reversed_i] + 1;

    }

  }

  return;

}

template <int V_max,list<int> E(const int&),int digit>
void DepthFirstSearchOnTree<V_max,E,digit>::SetDoubling()
{

  assert( !m_set_doubling );
  m_set_doubling = true;
  const int& V = DepthFirstSearch<V_max,E>::size();
  
  {
    
    vector<int>& doubling_0 = m_doubling[0];
    doubling_0.reserve( V );
    const int& r = Root();

    for( int i = 0 ; i < V ; i++ ){

      doubling_0.push_back( Parent( i ) );

    }

  }
  
  for( int d = 1 ; d < digit ; d++ ){

    vector<int>& doubling_d = m_doubling[d];
    vector<int>& doubling_d_minus = m_doubling[d-1];
    doubling_d.reserve( V );

    for( int i = 0 ; i < V ; i++ ){

      const int& doubling_d_minus_i = doubling_d_minus[i];
      doubling_d.push_back( doubling_d_minus_i == -1 ? -1 : doubling_d_minus[doubling_d_minus_i] );

    }

  }

  return;

}

template <int V_max,list<int> E(const int&),int digit> template <typename T , T f(const list<T>&,const int&)>
T DepthFirstSearchOnTree<V_max,E,digit>::RootingDP()
{

  if( ! m_set_children ){

    SetChildren();

  }
  
  const int& V = DepthFirstSearch<V_max,E>::size();
  list<T> children_value[V_max] = {};
  T temp;
  
  for( int n = 0 ; n < V ; n++ ){
    
    const int& i = NodeNumber( n , true );
    const int& j = Parent( i );
    temp = f( children_value[i] , i );

    if( j != -1 ){

      children_value[j].push_back( temp );

    }

  }

  return temp;

}
  
template <int V_max,list<int> E(const int&),int digit> template <typename T , T m_T(const T&,const T&) ,const T& e_T() , T f(const T&,const int&), T g(const T&,const bool&,const int&,const int&)>
void DepthFirstSearchOnTree<V_max,E,digit>::RerootingDP( T ( &d )[V_max] )
{

  if( ! m_set_children ){

    SetChildren();

  }
  
  const int& V = DepthFirstSearch<V_max,E>::size();
  const T& e = e_T();
  vector<T> children_value[V_max] = {};
  vector<T> left_sum[V_max] = {};
  vector<T> right_sum[V_max] = {};
  
  for( int i = 0 ; i < V ; i++ ){
    // iの各子ノードjに対するdp[0][j]を格納。
    children_value[i].resize( m_children[i].size() );

  }
  
  for( int n = 0 ; n < V ; n++ ){
    
    const int& i = NodeNumber( n , true );
    const vector<T>& children_value_i = children_value[i];
    const int size_i = children_value_i.size();

    T temp = e;
    vector<T>& left_sum_i = left_sum[i];
    left_sum_i.reserve( size_i + 1 );
    left_sum_i.push_back( temp );
    
    for( int m = 0 ; m < size_i ; m++ ){

      left_sum_i.push_back( temp = m_T( temp , g( children_value_i[m] , true , i , m_children[i][m] ) ) );

    }
    
    const int& j = Parent( i );

    if( j != -1 ){
      
      children_value[j][m_children_num[i]] = f( temp , i );

    }

    temp = e;
    vector<T>& right_sum_i = right_sum[i];
    right_sum_i.resize( size_i );

    for( int m = 1 ; m <= size_i ; m++ ){

      right_sum_i[ size_i - m ] = temp;
      temp = m_T( g( children_value_i[size_i - m] , true , i , m_children[i][size_i - m] ) , temp );

    }

  }

  for( int n = 1 ; n < V ; n++ ){
    
    const int& i = NodeNumber( n );
    const int& j = Parent( i );
    const int& k = ChildrenNumber( i );
    vector<T>& left_sum_i = left_sum[i];
    vector<T>& right_sum_i = right_sum[i];
    const int size_i = right_sum_i.size();
    const T rest_i = g( f( m_T( left_sum[j][k] , right_sum[j][k] ) , j ) , false , i , j );
    
    for( int m = 0 ; m <= size_i ; m++ ){

      T& left_sum_im = left_sum_i[m];
      left_sum_im = m_T( rest_i , left_sum_im );

    }

  }

  for( int i = 0 ; i < V ; i++ ){

    d[i] = f( left_sum[i].back() , i );

  }

  return;

}
  
// AAA 常設でないライブラリは以上に挿入する。

#define INCLUDE_SUB
#include __FILE__

#else // INCLUDE_LIBRARY

// #define REACTIVE
// #define USE_GETLINE
#ifdef DEBUG
  #define _GLIBCXX_DEBUG
#define REPEAT_MAIN( BOUND ) START_MAIN; signal( SIGABRT , &AlertAbort ); AutoCheck( exec_mode , use_getline ); if( exec_mode == sample_debug_mode || exec_mode == submission_debug_mode || exec_mode == library_search_mode ){ return 0; } else if( exec_mode == experiment_mode ){ Experiment(); return 0; } else if( exec_mode == small_test_mode ){ SmallTest(); return 0; }; DEXPR( int , bound_test_case_num , BOUND , min( BOUND , 100 ) ); int test_case_num = 1; if( exec_mode == solve_mode ){ if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } } else if( exec_mode == random_test_mode ){ CERR( "ランダムテストを行う回数を指定してください。" ); SET_LL( test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , DEBUG_VALUE )
  #define ASSERT( A , MIN , MAX ) CERR( "ASSERTチェック: " , ( MIN ) , ( ( MIN ) <= A ? "<=" : ">" ) , A , ( A <= ( MAX ) ? "<=" : ">" ) , ( MAX ) ); assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) if( exec_mode == solve_mode ){ SET_LL( A ); ASSERT( A , MIN , MAX ); } else if( exec_mode == random_test_mode ){ CERR( #A , " = " , ( A = GetRand( MIN , MAX ) ) ); } else { assert( false ); }
  #define SOLVE_ONLY static_assert( __FUNCTION__[0] == 'S' )
  #define CERR( ... ) VariadicCout( cerr , __VA_ARGS__ ) << endl
  #define COUT( ... ) VariadicCout( cout << "出力: " , __VA_ARGS__ ) << endl
  #define CERR_A( A , N ) OUTPUT_ARRAY( cerr , A , N ) << endl
  #define COUT_A( A , N ) cout << "出力: "; OUTPUT_ARRAY( cout , A , N ) << endl
  #define CERR_ITR( A ) OUTPUT_ITR( cerr , A ) << endl
  #define COUT_ITR( A ) cout << "出力: "; OUTPUT_ITR( cout , A ) << endl
#else
  #pragma GCC optimize ( "O3" )
  #pragma GCC optimize ( "unroll-loops" )
  #pragma GCC target ( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" )
  #define REPEAT_MAIN( BOUND ) START_MAIN; CEXPR( int , bound_test_case_num , BOUND ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , VALUE )
  #define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) SET_LL( A ); ASSERT( A , MIN , MAX )
  #define SOLVE_ONLY 
  #define CERR( ... ) 
  #define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << ENDL
  #define CERR_A( A , N ) 
  #define COUT_A( A , N ) OUTPUT_ARRAY( cout , A , N ) << ENDL
  #define CERR_ITR( A ) 
  #define COUT_ITR( A ) OUTPUT_ITR( cout , A ) << ENDL
#endif
#ifdef REACTIVE
  #define ENDL endl
#else
  #define ENDL "\n"
#endif
#ifdef USE_GETLINE
  #define SET_LL( A ) { GETLINE( A ## _str ); A = stoll( A ## _str ); }
  #define GETLINE_SEPARATE( SEPARATOR , ... ) SOLVE_ONLY; string __VA_ARGS__; VariadicGetline( cin , SEPARATOR , __VA_ARGS__ )
  #define GETLINE( ... ) SOLVE_ONLY; GETLINE_SEPARATE( '\n' , __VA_ARGS__ )
#else
  #define SET_LL( A ) cin >> A
  #define CIN( LL , ... ) SOLVE_ONLY; LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ )
  #define SET_A( A , N ) SOLVE_ONLY; FOR( VARIABLE_FOR_CIN_A , 0 , N ){ cin >> A[VARIABLE_FOR_CIN_A]; }
  #define CIN_A( LL , A , N ) vector<LL> A( N ); SET_A( A , N );
#endif
#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using lld = __float128;
template <typename INT> using T2 = pair<INT,INT>;
template <typename INT> using T3 = tuple<INT,INT,INT>;
template <typename INT> using T4 = tuple<INT,INT,INT,INT>;
using path = pair<int,ll>;
#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 FINISH_MAIN REPEAT( test_case_num ){ if constexpr( bound_test_case_num > 1 ){ CERR( "testcase " , VARIABLE_FOR_REPEAT_test_case_num , ":" ); } Solve(); CERR( "" ); } }
#define START_WATCH chrono::system_clock::time_point watch = chrono::system_clock::now()
#define CURRENT_TIME static_cast<double>( chrono::duration_cast<chrono::microseconds>( chrono::system_clock::now() - watch ).count() / 1000.0 )
#define CHECK_WATCH( TL_MS ) ( CURRENT_TIME < TL_MS - 100.0 )
#define TYPE_OF( VAR ) decay_t<decltype( VAR )>
#define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE
#define CIN_ASSERT( A , MIN , MAX ) TYPE_OF( MAX ) A; SET_ASSERT( A , MIN , MAX )
#define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( TYPE_OF( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ )
#define FOREQ( VAR , INITIAL , FINAL ) for( TYPE_OF( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ )
#define FOREQINV( VAR , INITIAL , FINAL ) for( TYPE_OF( INITIAL ) VAR = INITIAL ; VAR >= FINAL ; VAR -- )
#define AUTO_ITR( ARRAY ) auto itr_ ## ARRAY = ARRAY .begin() , end_ ## ARRAY = ARRAY .end()
#define FOR_ITR( ARRAY ) for( AUTO_ITR( ARRAY ) , itr = itr_ ## ARRAY ; itr_ ## ARRAY != end_ ## ARRAY ; itr_ ## ARRAY ++ , itr++ )
#define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT_ ## HOW_MANY_TIMES , 0 , HOW_MANY_TIMES )
#define SET_PRECISION( DECIMAL_DIGITS ) cout << fixed << setprecision( DECIMAL_DIGITS )
#define OUTPUT_ARRAY( OS , A , N ) FOR( VARIABLE_FOR_OUTPUT_ARRAY , 0 , N ){ OS << A[VARIABLE_FOR_OUTPUT_ARRAY] << (VARIABLE_FOR_OUTPUT_ARRAY==N-1?"":" "); } OS
#define OUTPUT_ITR( OS , A ) { auto ITERATOR_FOR_OUTPUT_ITR = A.begin() , END_FOR_OUTPUT_ITR = A.end(); bool VARIABLE_FOR_OUTPUT_ITR = ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR; while( VARIABLE_FOR_OUTPUT_ITR ){ OS << *ITERATOR_FOR_COUT_ITR; ( VARIABLE_FOR_OUTPUT_ITR = ++ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR ) ? OS : OS << " "; } } OS
#define RETURN( ... ) SOLVE_ONLY; COUT( __VA_ARGS__ ); return
#define COMPARE( ... ) auto naive = Naive( __VA_ARGS__ ); auto answer = Answer( __VA_ARGS__ ); bool match = naive == answer; COUT( #__VA_ARGS__ , ":" , naive , match ? "==" : "!=" , answer ); if( !match ){ return; }

// 入出力用
template <class Traits> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is , Arg& arg , ARGS&... args ) { return VariadicCin( is >> arg , args... ); }
template <class Traits> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator , Arg& arg , ARGS&... args ) { return VariadicGetline( getline( is , arg , separator ) , separator , args... ); }
template <class Traits , typename Arg> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg& arg ) { return os << arg; }
template <class Traits , typename Arg1 , typename Arg2 , typename... ARGS> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg1& arg1 , const Arg2& arg2 , const ARGS&... args ) { return VariadicCout( os << arg1 << " " , arg2 , args... ); }

// グラフ用
template <typename PATH> vector<list<PATH> > e;
template <typename T> map<T,T> f;
template <typename T> vector<T> g;

// デバッグ用
#ifdef DEBUG
  inline void AlertAbort( int n ) { CERR( "abort関数が呼ばれました。assertマクロのメッセージが出力されていない場合はオーバーフローの有無を確認をしてください。" ); }
  void AutoCheck( int& exec_mode , const bool& use_getline );
  inline void Solve();
  inline void Experiment();
  inline void SmallTest();
  inline void RandomTest();
  ll GetRand( const ll& Rand_min , const ll& Rand_max );
  int exec_mode;
  CEXPR( int , solve_mode , 0 );
  CEXPR( int , sample_debug_mode , 1 );
  CEXPR( int , submission_debug_mode , 2 );
  CEXPR( int , library_search_mode , 3 );
  CEXPR( int , experiment_mode , 4 );
  CEXPR( int , small_test_mode , 5 );
  CEXPR( int , random_test_mode , 6 );
  #ifdef USE_GETLINE
    CEXPR( bool , use_getline , true );
  #else
    CEXPR( bool , use_getline , false );
  #endif
#else
  ll GetRand( const ll& , const ll& ) { abort(); return 0; }
#endif

// 圧縮用
#define TE template
#define TY typename
#define US using
#define ST static
#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 MO move
#define TH this
#define CRI CO int&
#define CRUI CO uint&
#define CRL CO ll&

// VVV 常設ライブラリは以下に挿入する。

// ConstexprModulo
// c:/Users/user/Documents/Programming/Mathematics/Arithmetic/Mod/ConstexprModulo/a.hpp
CEXPR(uint,P,998244353);TE <uint M,TY INT> CE INT& RS(INT& n)NE{RE n < 0?((((++n)*= -1)%= M)*= -1)+= M - 1:n %= M;}TE <uint M> CE uint& RS(uint& n)NE{RE n %= M;}TE <uint M> CE ull& RS(ull& n)NE{RE n %= M;}TE <TY INT> CE INT& RSP(INT& n)NE{CE CO uint trunc =(1 << 23)- 1;INT n_u = n >> 23;n &= trunc;INT n_uq =(n_u / 7)/ 17;n_u -= n_uq * 119;n += n_u << 23;RE n < n_uq?n += P - n_uq:n -= n_uq;}TE <> CE ull& RS<P,ull>(ull& n)NE{CE CO ull Pull = P;CE CO ull Pull2 =(Pull - 1)*(Pull - 1);RE RSP(n > Pull2?n -= Pull2:n);}TE <uint M,TY INT> CE INT RS(INT&& n)NE{RE MO(RS<M>(n));}TE <uint M,TY INT> CE INT RS(CO INT& n)NE{RE RS<M>(INT(n));}

#define SFINAE_FOR_MOD(DEFAULT)TY T,enable_if_t<is_constructible<uint,decay_t<T> >::value>* DEFAULT
#define DC_OF_CM_FOR_MOD(FUNC)CE bool OP FUNC(CO Mod<M>& n)CO NE
#define DC_OF_AR_FOR_MOD(FUNC)CE Mod<M> OP FUNC(CO Mod<M>& n)CO NE;TE <SFINAE_FOR_MOD(= nullptr)> CE Mod<M> OP FUNC(T&& n)CO NE;
#define DF_OF_CM_FOR_MOD(FUNC)TE <uint M> CE bool Mod<M>::OP FUNC(CO Mod<M>& n)CO NE{RE m_n FUNC n.m_n;}
#define DF_OF_AR_FOR_MOD(FUNC,FORMULA)TE <uint M> CE Mod<M> Mod<M>::OP FUNC(CO Mod<M>& n)CO NE{RE MO(Mod<M>(*TH)FUNC ## = n);}TE <uint M> TE <SFINAE_FOR_MOD()> CE Mod<M> Mod<M>::OP FUNC(T&& n)CO NE{RE FORMULA;}TE <uint M,SFINAE_FOR_MOD(= nullptr)> CE Mod<M> OP FUNC(T&& n0,CO Mod<M>& n1)NE{RE MO(Mod<M>(forward<T>(n0))FUNC ## = n1);}

TE <uint M>CL Mod{PU:uint m_n;CE Mod()NE;CE Mod(CO Mod<M>& n)NE;CE Mod(Mod<M>& n)NE;CE Mod(Mod<M>&& n)NE;TE <SFINAE_FOR_MOD(= nullptr)> CE Mod(CO T& n)NE;TE <SFINAE_FOR_MOD(= nullptr)> CE Mod(T& n)NE;TE <SFINAE_FOR_MOD(= nullptr)> CE Mod(T&& n)NE;CE Mod<M>& OP=(CO Mod<M>& n)NE;CE Mod<M>& OP=(Mod<M>&& n)NE;CE Mod<M>& OP+=(CO Mod<M>& n)NE;CE Mod<M>& OP-=(CO Mod<M>& n)NE;CE Mod<M>& OP*=(CO Mod<M>& n)NE;IN Mod<M>& OP/=(CO Mod<M>& n);CE Mod<M>& OP<<=(int n)NE;CE Mod<M>& OP>>=(int n)NE;CE Mod<M>& OP++()NE;CE Mod<M> OP++(int)NE;CE Mod<M>& OP--()NE;CE Mod<M> OP--(int)NE;DC_OF_CM_FOR_MOD(==);DC_OF_CM_FOR_MOD(!=);DC_OF_CM_FOR_MOD(<);DC_OF_CM_FOR_MOD(<=);DC_OF_CM_FOR_MOD(>);DC_OF_CM_FOR_MOD(>=);DC_OF_AR_FOR_MOD(+);DC_OF_AR_FOR_MOD(-);DC_OF_AR_FOR_MOD(*);DC_OF_AR_FOR_MOD(/);CE Mod<M> OP<<(int n)CO NE;CE Mod<M> OP>>(int n)CO NE;CE Mod<M> OP-()CO NE;CE Mod<M>& SignInvert()NE;CE Mod<M>& Double()NE;CE Mod<M>& Halve()NE;IN Mod<M>& Invert();TE <TY T> CE Mod<M>& PositivePW(T&& EX)NE;TE <TY T> CE Mod<M>& NonNegativePW(T&& EX)NE;TE <TY T> CE Mod<M>& PW(T&& EX);CE VO swap(Mod<M>& n)NE;CE CRUI RP()CO NE;ST CE Mod<M> DeRP(CRUI n)NE;ST CE uint& Normalise(uint& n)NE;ST IN CO Mod<M>& Inverse(CRUI n)NE;ST IN CO Mod<M>& Factorial(CRUI n)NE;ST IN CO Mod<M>& FactorialInverse(CRUI n)NE;ST IN Mod<M> Combination(CRUI n,CRUI i)NE;ST IN CO Mod<M>& zero()NE;ST IN CO Mod<M>& one()NE;TE <TY T> CE Mod<M>& Ref(T&& n)NE;};

#define SFINAE_FOR_MN(DEFAULT)TY T,enable_if_t<is_constructible<Mod<M>,decay_t<T> >::value>* DEFAULT
#define DC_OF_AR_FOR_MN(FUNC)IN MN<M> OP FUNC(CO MN<M>& n)CO NE;TE <SFINAE_FOR_MOD(= nullptr)> IN MN<M> OP FUNC(T&& n)CO NE;
#define DF_OF_CM_FOR_MN(FUNC)TE <uint M> IN bool MN<M>::OP FUNC(CO MN<M>& n)CO NE{RE m_n FUNC n.m_n;}
#define DF_OF_AR_FOR_MN(FUNC,FORMULA)TE <uint M> IN MN<M> MN<M>::OP FUNC(CO MN<M>& n)CO NE{RE MO(MN<M>(*TH)FUNC ## = n);}TE <uint M> TE <SFINAE_FOR_MOD()> IN MN<M> MN<M>::OP FUNC(T&& n)CO NE{RE FORMULA;}TE <uint M,SFINAE_FOR_MOD(= nullptr)> IN MN<M> OP FUNC(T&& n0,CO MN<M>& n1)NE{RE MO(MN<M>(forward<T>(n0))FUNC ## = n1);}

TE <uint M>CL MN:PU Mod<M>{PU:CE MN()NE;CE MN(CO MN<M>& n)NE;CE MN(MN<M>& n)NE;CE MN(MN<M>&& n)NE;TE <SFINAE_FOR_MN(= nullptr)> CE MN(CO T& n)NE;TE <SFINAE_FOR_MN(= nullptr)> CE MN(T&& n)NE;CE MN<M>& OP=(CO MN<M>& n)NE;CE MN<M>& OP=(MN<M>&& n)NE;CE MN<M>& OP+=(CO MN<M>& n)NE;CE MN<M>& OP-=(CO MN<M>& n)NE;CE MN<M>& OP*=(CO MN<M>& n)NE;IN MN<M>& OP/=(CO MN<M>& n);CE MN<M>& OP<<=(int n)NE;CE MN<M>& OP>>=(int n)NE;CE MN<M>& OP++()NE;CE MN<M> OP++(int)NE;CE MN<M>& OP--()NE;CE MN<M> OP--(int)NE;DC_OF_AR_FOR_MN(+);DC_OF_AR_FOR_MN(-);DC_OF_AR_FOR_MN(*);DC_OF_AR_FOR_MN(/);CE MN<M> OP<<(int n)CO NE;CE MN<M> OP>>(int n)CO NE;CE MN<M> OP-()CO NE;CE MN<M>& SignInvert()NE;CE MN<M>& Double()NE;CE MN<M>& Halve()NE;CE MN<M>& Invert();TE <TY T> CE MN<M>& PositivePW(T&& EX)NE;TE <TY T> CE MN<M>& NonNegativePW(T&& EX)NE;TE <TY T> CE MN<M>& PW(T&& EX);CE uint RP()CO NE;CE Mod<M> Reduce()CO NE;ST CE MN<M> DeRP(CRUI n)NE;ST IN CO MN<M>& Formise(CRUI n)NE;ST IN CO MN<M>& Inverse(CRUI n)NE;ST IN CO MN<M>& Factorial(CRUI n)NE;ST IN CO MN<M>& FactorialInverse(CRUI n)NE;ST IN MN<M> Combination(CRUI n,CRUI i)NE;ST IN CO MN<M>& zero()NE;ST IN CO MN<M>& one()NE;ST CE uint Form(CRUI n)NE;ST CE ull& Reduction(ull& n)NE;ST CE ull& ReducedMU(ull& n,CRUI m)NE;ST CE uint MU(CRUI n0,CRUI n1)NE;ST CE uint BaseSquareTruncation(uint& n)NE;TE <TY T> CE MN<M>& Ref(T&& n)NE;};TE <uint M> CE MN<M> Twice(CO MN<M>& n)NE;TE <uint M> CE MN<M> Half(CO MN<M>& n)NE;TE <uint M> CE MN<M> Inverse(CO MN<M>& n);TE <uint M,TY T> CE MN<M> PW(MN<M> n,T EX);TE <TY T> CE MN<2> PW(CO MN<2>& n,CO T& p);TE <TY T> CE T Square(CO T& t);TE <> CE MN<2> Square<MN<2> >(CO MN<2>& t);TE <uint M> CE VO swap(MN<M>& n0,MN<M>& n1)NE;TE <uint M> IN string to_string(CO MN<M>& n)NE;TE<uint M,CL Traits> IN basic_istream<char,Traits>& OP>>(basic_istream<char,Traits>& is,MN<M>& n);TE<uint M,CL Traits> IN basic_ostream<char,Traits>& OP<<(basic_ostream<char,Traits>& os,CO MN<M>& n);

TE <uint M>CL COantsForMod{PU:COantsForMod()= delete;ST CE CO bool g_even =((M & 1)== 0);ST CE CO uint g_memory_bound = 1000000;ST CE CO uint g_memory_LE = M < g_memory_bound?M:g_memory_bound;ST CE ull MNBasePW(ull&& EX)NE;ST CE uint g_M_minus = M - 1;ST CE uint g_M_minus_2 = M - 2;ST CE uint g_M_minus_2_neg = 2 - M;ST CE CO int g_MN_digit = 32;ST CE CO ull g_MN_base = ull(1)<< g_MN_digit;ST CE CO uint g_MN_base_minus = uint(g_MN_base - 1);ST CE CO uint g_MN_digit_half =(g_MN_digit + 1)>> 1;ST CE CO uint g_MN_base_sqrt_minus =(1 << g_MN_digit_half)- 1;ST CE CO uint g_MN_M_neg_inverse = uint((g_MN_base - MNBasePW((ull(1)<<(g_MN_digit - 1))- 1))& g_MN_base_minus);ST CE CO uint g_MN_base_mod = uint(g_MN_base % M);ST CE CO uint g_MN_base_square_mod = uint(((g_MN_base % M)*(g_MN_base % M))% M);};TE <uint M> CE ull COantsForMod<M>::MNBasePW(ull&& EX)NE{ull prod = 1;ull PW = M;WH(EX != 0){(EX & 1)== 1?(prod *= PW)&= g_MN_base_minus:prod;EX >>= 1;(PW *= PW)&= g_MN_base_minus;}RE prod;}

US MP = Mod<P>;US MNP = MN<P>;TE <uint M> CE uint MN<M>::Form(CRUI n)NE{ull n_copy = n;RE uint(MO(Reduction(n_copy *= COantsForMod<M>::g_MN_base_square_mod)));}TE <uint M> CE ull& MN<M>::Reduction(ull& n)NE{ull n_sub = n & COantsForMod<M>::g_MN_base_minus;RE((n +=((n_sub *= COantsForMod<M>::g_MN_M_neg_inverse)&= COantsForMod<M>::g_MN_base_minus)*= M)>>= COantsForMod<M>::g_MN_digit)< M?n:n -= M;}TE <uint M> CE ull& MN<M>::ReducedMU(ull& n,CRUI m)NE{RE Reduction(n *= m);}TE <uint M> CE uint MN<M>::MU(CRUI n0,CRUI n1)NE{ull n0_copy = n0;RE uint(MO(ReducedMU(ReducedMU(n0_copy,n1),COantsForMod<M>::g_MN_base_square_mod)));}TE <uint M> CE uint MN<M>::BaseSquareTruncation(uint& n)NE{CO uint n_u = n >> COantsForMod<M>::g_MN_digit_half;n &= COantsForMod<M>::g_MN_base_sqrt_minus;RE n_u;}TE <uint M> CE MN<M>::MN()NE:Mod<M>(){static_assert(! COantsForMod<M>::g_even);}TE <uint M> CE MN<M>::MN(CO MN<M>& n)NE:Mod<M>(n){}TE <uint M> CE MN<M>::MN(MN<M>& n)NE:Mod<M>(n){}TE <uint M> CE MN<M>::MN(MN<M>&& n)NE:Mod<M>(MO(n)){}TE <uint M> TE <SFINAE_FOR_MN()> CE MN<M>::MN(CO T& n)NE:Mod<M>(n){static_assert(! COantsForMod<M>::g_even);Mod<M>::m_n = Form(Mod<M>::m_n);}TE <uint M> TE <SFINAE_FOR_MN()> CE MN<M>::MN(T&& n)NE:Mod<M>(forward<T>(n)){static_assert(! COantsForMod<M>::g_even);Mod<M>::m_n = Form(Mod<M>::m_n);}TE <uint M> CE MN<M>& MN<M>::OP=(CO MN<M>& n)NE{RE Ref(Mod<M>::OP=(n));}TE <uint M> CE MN<M>& MN<M>::OP=(MN<M>&& n)NE{RE Ref(Mod<M>::OP=(MO(n)));}TE <uint M> CE MN<M>& MN<M>::OP+=(CO MN<M>& n)NE{RE Ref(Mod<M>::OP+=(n));}TE <uint M> CE MN<M>& MN<M>::OP-=(CO MN<M>& n)NE{RE Ref(Mod<M>::OP-=(n));}TE <uint M> CE MN<M>& MN<M>::OP*=(CO MN<M>& n)NE{ull m_n_copy = Mod<M>::m_n;RE Ref(Mod<M>::m_n = MO(ReducedMU(m_n_copy,n.m_n)));}TE <uint M> IN MN<M>& MN<M>::OP/=(CO MN<M>& n){RE OP*=(MN<M>(n).Invert());}TE <uint M> CE MN<M>& MN<M>::OP<<=(int n)NE{RE Ref(Mod<M>::OP<<=(n));}TE <uint M> CE MN<M>& MN<M>::OP>>=(int n)NE{RE Ref(Mod<M>::OP>>=(n));}TE <uint M> CE MN<M>& MN<M>::OP++()NE{RE Ref(Mod<M>::Normalise(Mod<M>::m_n += COantsForMod<M>::g_MN_base_mod));}TE <uint M> CE MN<M> MN<M>::OP++(int)NE{MN<M> n{*TH};OP++();RE n;}TE <uint M> CE MN<M>& MN<M>::OP--()NE{RE Ref(Mod<M>::m_n < COantsForMod<M>::g_MN_base_mod?((Mod<M>::m_n += M)-= COantsForMod<M>::g_MN_base_mod):Mod<M>::m_n -= COantsForMod<M>::g_MN_base_mod);}TE <uint M> CE MN<M> MN<M>::OP--(int)NE{MN<M> n{*TH};OP--();RE n;}DF_OF_AR_FOR_MN(+,MN<M>(forward<T>(n))+= *TH);DF_OF_AR_FOR_MN(-,MN<M>(forward<T>(n)).SignInvert()+= *TH);DF_OF_AR_FOR_MN(*,MN<M>(forward<T>(n))*= *TH);DF_OF_AR_FOR_MN(/,MN<M>(forward<T>(n)).Invert()*= *TH);TE <uint M> CE MN<M> MN<M>::OP<<(int n)CO NE{RE MO(MN<M>(*TH)<<= n);}TE <uint M> CE MN<M> MN<M>::OP>>(int n)CO NE{RE MO(MN<M>(*TH)>>= n);}TE <uint M> CE MN<M> MN<M>::OP-()CO NE{RE MO(MN<M>(*TH).SignInvert());}TE <uint M> CE MN<M>& MN<M>::SignInvert()NE{RE Ref(Mod<M>::m_n > 0?Mod<M>::m_n = M - Mod<M>::m_n:Mod<M>::m_n);}TE <uint M> CE MN<M>& MN<M>::Double()NE{RE Ref(Mod<M>::Double());}TE <uint M> CE MN<M>& MN<M>::Halve()NE{RE Ref(Mod<M>::Halve());}TE <uint M> CE MN<M>& MN<M>::Invert(){assert(Mod<M>::m_n > 0);RE PositivePW(uint(COantsForMod<M>::g_M_minus_2));}TE <uint M> TE <TY T> CE MN<M>& MN<M>::PositivePW(T&& EX)NE{MN<M> PW{*TH};(--EX)%= COantsForMod<M>::g_M_minus_2;WH(EX != 0){(EX & 1)== 1?OP*=(PW):*TH;EX >>= 1;PW *= PW;}RE *TH;}TE <uint M> TE <TY T> CE MN<M>& MN<M>::NonNegativePW(T&& EX)NE{RE EX == 0?Ref(Mod<M>::m_n = COantsForMod<M>::g_MN_base_mod):PositivePW(forward<T>(EX));}TE <uint M> TE <TY T> CE MN<M>& MN<M>::PW(T&& EX){bool neg = EX < 0;assert(!(neg && Mod<M>::m_n == 0));RE neg?PositivePW(forward<T>(EX *= COantsForMod<M>::g_M_minus_2_neg)):NonNegativePW(forward<T>(EX));}TE <uint M> CE uint MN<M>::RP()CO NE{ull m_n_copy = Mod<M>::m_n;RE MO(Reduction(m_n_copy));}TE <uint M> CE Mod<M> MN<M>::Reduce()CO NE{ull m_n_copy = Mod<M>::m_n;RE Mod<M>::DeRP(MO(Reduction(m_n_copy)));}TE <uint M> CE MN<M> MN<M>::DeRP(CRUI n)NE{RE MN<M>(Mod<M>::DeRP(n));}TE <uint M> IN CO MN<M>& MN<M>::Formise(CRUI n)NE{ST MN<M> memory[COantsForMod<M>::g_memory_LE] ={zero(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory[LE_curr] = DeRP(LE_curr);LE_curr++;}RE memory[n];}TE <uint M> IN CO MN<M>& MN<M>::Inverse(CRUI n)NE{ST MN<M> memory[COantsForMod<M>::g_memory_LE] ={zero(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory[LE_curr] = MN<M>(Mod<M>::Inverse(LE_curr));LE_curr++;}RE memory[n];}TE <uint M> IN CO MN<M>& MN<M>::Factorial(CRUI n)NE{ST MN<M> memory[COantsForMod<M>::g_memory_LE] ={one(),one()};ST uint LE_curr = 2;ST MN<M> val_curr{one()};ST MN<M> val_last{one()};WH(LE_curr <= n){memory[LE_curr++] = val_curr *= ++val_last;}RE memory[n];}TE <uint M> IN CO MN<M>& MN<M>::FactorialInverse(CRUI n)NE{ST MN<M> memory[COantsForMod<M>::g_memory_LE] ={one(),one()};ST uint LE_curr = 2;ST MN<M> val_curr{one()};ST MN<M> val_last{one()};WH(LE_curr <= n){memory[LE_curr] = val_curr *= Inverse(LE_curr);LE_curr++;}RE memory[n];}TE <uint M> IN MN<M> MN<M>::Combination(CRUI n,CRUI i)NE{RE i <= n?Factorial(n)*FactorialInverse(i)*FactorialInverse(n - i):zero();}TE <uint M> IN CO MN<M>& MN<M>::zero()NE{ST CE CO MN<M> z{};RE z;}TE <uint M> IN CO MN<M>& MN<M>::one()NE{ST CE CO MN<M> o{DeRP(1)};RE o;}TE <uint M> TE <TY T> CE MN<M>& MN<M>::Ref(T&& n)NE{RE *TH;}TE <uint M> CE MN<M> Twice(CO MN<M>& n)NE{RE MO(MN<M>(n).Double());}TE <uint M> CE MN<M> Half(CO MN<M>& n)NE{RE MO(MN<M>(n).Halve());}TE <uint M> CE MN<M> Inverse(CO MN<M>& n){RE MO(MN<M>(n).Invert());}TE <uint M,TY T> CE MN<M> PW(MN<M> n,T EX){RE MO(n.PW(EX));}TE <uint M> CE VO swap(MN<M>& n0,MN<M>& n1)NE{n0.swap(n1);}TE <uint M> IN string to_string(CO MN<M>& n)NE{RE to_string(n.RP())+ " + MZ";}TE<uint M,CL Traits> IN basic_istream<char,Traits>& OP>>(basic_istream<char,Traits>& is,MN<M>& n){ll m;is >> m;n = m;RE is;}TE<uint M,CL Traits> IN basic_ostream<char,Traits>& OP<<(basic_ostream<char,Traits>& os,CO MN<M>& n){RE os << n.RP();}

TE <uint M> CE Mod<M>::Mod()NE:m_n(){}TE <uint M> CE Mod<M>::Mod(CO Mod<M>& n)NE:m_n(n.m_n){}TE <uint M> CE Mod<M>::Mod(Mod<M>& n)NE:m_n(n.m_n){}TE <uint M> CE Mod<M>::Mod(Mod<M>&& n)NE:m_n(MO(n.m_n)){}TE <uint M> TE <SFINAE_FOR_MOD()> CE Mod<M>::Mod(CO T& n)NE:m_n(RS<M>(n)){}TE <uint M> TE <SFINAE_FOR_MOD()> CE Mod<M>::Mod(T& n)NE:m_n(RS<M>(decay_t<T>(n))){}TE <uint M> TE <SFINAE_FOR_MOD()> CE Mod<M>::Mod(T&& n)NE:m_n(RS<M>(forward<T>(n))){}TE <uint M> CE Mod<M>& Mod<M>::OP=(CO Mod<M>& n)NE{RE Ref(m_n = n.m_n);}TE <uint M> CE Mod<M>& Mod<M>::OP=(Mod<M>&& n)NE{RE Ref(m_n = MO(n.m_n));}TE <uint M> CE Mod<M>& Mod<M>::OP+=(CO Mod<M>& n)NE{RE Ref(Normalise(m_n += n.m_n));}TE <uint M> CE Mod<M>& Mod<M>::OP-=(CO Mod<M>& n)NE{RE Ref(m_n < n.m_n?(m_n += M)-= n.m_n:m_n -= n.m_n);}TE <uint M> CE Mod<M>& Mod<M>::OP*=(CO Mod<M>& n)NE{RE Ref(m_n = COantsForMod<M>::g_even?RS<M>(ull(m_n)* n.m_n):MN<M>::MU(m_n,n.m_n));}TE <> CE MP& MP::OP*=(CO MP& n)NE{ull m_n_copy = m_n;RE Ref(m_n = MO((m_n_copy *= n.m_n)< P?m_n_copy:RSP(m_n_copy)));}TE <uint M> IN Mod<M>& Mod<M>::OP/=(CO Mod<M>& n){RE OP*=(Mod<M>(n).Invert());}TE <uint M> CE Mod<M>& Mod<M>::OP<<=(int n)NE{WH(n-- > 0){Normalise(m_n <<= 1);}RE *TH;}TE <uint M> CE Mod<M>& Mod<M>::OP>>=(int n)NE{WH(n-- > 0){((m_n & 1)== 0?m_n:m_n += M)>>= 1;}RE *TH;}TE <uint M> CE Mod<M>& Mod<M>::OP++()NE{RE Ref(m_n < COantsForMod<M>::g_M_minus?++m_n:m_n = 0);}TE <uint M> CE Mod<M> Mod<M>::OP++(int)NE{Mod<M> n{*TH};OP++();RE n;}TE <uint M> CE Mod<M>& Mod<M>::OP--()NE{RE Ref(m_n == 0?m_n = COantsForMod<M>::g_M_minus:--m_n);}TE <uint M> CE Mod<M> Mod<M>::OP--(int)NE{Mod<M> n{*TH};OP--();RE n;}DF_OF_CM_FOR_MOD(==);DF_OF_CM_FOR_MOD(!=);DF_OF_CM_FOR_MOD(>);DF_OF_CM_FOR_MOD(>=);DF_OF_CM_FOR_MOD(<);DF_OF_CM_FOR_MOD(<=);DF_OF_AR_FOR_MOD(+,Mod<M>(forward<T>(n))+= *TH);DF_OF_AR_FOR_MOD(-,Mod<M>(forward<T>(n)).SignInvert()+= *TH);DF_OF_AR_FOR_MOD(*,Mod<M>(forward<T>(n))*= *TH);DF_OF_AR_FOR_MOD(/,Mod<M>(forward<T>(n)).Invert()*= *TH);TE <uint M> CE Mod<M> Mod<M>::OP<<(int n)CO NE{RE MO(Mod<M>(*TH)<<= n);}TE <uint M> CE Mod<M> Mod<M>::OP>>(int n)CO NE{RE MO(Mod<M>(*TH)>>= n);}TE <uint M> CE Mod<M> Mod<M>::OP-()CO NE{RE MO(Mod<M>(*TH).SignInvert());}TE <uint M> CE Mod<M>& Mod<M>::SignInvert()NE{RE Ref(m_n > 0?m_n = M - m_n:m_n);}TE <uint M> CE Mod<M>& Mod<M>::Double()NE{RE Ref(Normalise(m_n <<= 1));}TE <uint M> CE Mod<M>& Mod<M>::Halve()NE{RE Ref(((m_n & 1)== 0?m_n:m_n += M)>>= 1);}TE <uint M> IN Mod<M>& Mod<M>::Invert(){assert(m_n > 0);uint m_n_neg;RE m_n < COantsForMod<M>::g_memory_LE?Ref(m_n = Inverse(m_n).m_n):((m_n_neg = M - m_n)< COantsForMod<M>::g_memory_LE)?Ref(m_n = M - Inverse(m_n_neg).m_n):PositivePW(uint(COantsForMod<M>::g_M_minus_2));}TE <> IN Mod<2>& Mod<2>::Invert(){assert(m_n > 0);RE *TH;}TE <uint M> TE <TY T> CE Mod<M>& Mod<M>::PositivePW(T&& EX)NE{Mod<M> PW{*TH};EX--;WH(EX != 0){(EX & 1)== 1?OP*=(PW):*TH;EX >>= 1;PW *= PW;}RE *TH;}TE <> TE <TY T> CE Mod<2>& Mod<2>::PositivePW(T&& EX)NE{RE *TH;}TE <uint M> TE <TY T> CE Mod<M>& Mod<M>::NonNegativePW(T&& EX)NE{RE EX == 0?Ref(m_n = 1):Ref(PositivePW(forward<T>(EX)));}TE <uint M> TE <TY T> CE Mod<M>& Mod<M>::PW(T&& EX){bool neg = EX < 0;assert(!(neg && m_n == 0));neg?EX *= COantsForMod<M>::g_M_minus_2_neg:EX;RE m_n == 0?*TH:(EX %= COantsForMod<M>::g_M_minus)== 0?Ref(m_n = 1):PositivePW(forward<T>(EX));}TE <uint M> IN CO Mod<M>& Mod<M>::Inverse(CRUI n)NE{ST Mod<M> memory[COantsForMod<M>::g_memory_LE] ={zero(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory[LE_curr].m_n = M - MN<M>::MU(memory[M % LE_curr].m_n,M / LE_curr);LE_curr++;}RE memory[n];}TE <uint M> IN CO Mod<M>& Mod<M>::Factorial(CRUI n)NE{ST Mod<M> memory[COantsForMod<M>::g_memory_LE] ={one(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory[LE_curr] = MN<M>::Factorial(LE_curr).Reduce();LE_curr++;}RE memory[n];}TE <uint M> IN CO Mod<M>& Mod<M>::FactorialInverse(CRUI n)NE{ST Mod<M> memory[COantsForMod<M>::g_memory_LE] ={one(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory[LE_curr] = MN<M>::FactorialInverse(LE_curr).Reduce();LE_curr++;}RE memory[n];}TE <uint M> IN Mod<M> Mod<M>::Combination(CRUI n,CRUI i)NE{RE MN<M>::Combination(n,i).Reduce();}TE <uint M> CE VO Mod<M>::swap(Mod<M>& n)NE{std::swap(m_n,n.m_n);}TE <uint M> CE CRUI Mod<M>::RP()CO NE{RE m_n;}TE <uint M> CE Mod<M> Mod<M>::DeRP(CRUI n)NE{Mod<M> n_copy{};n_copy.m_n = n;RE n_copy;}TE <uint M> CE uint& Mod<M>::Normalise(uint& n)NE{RE n < M?n:n -= M;}TE <uint M> IN CO Mod<M>& Mod<M>::zero()NE{ST CE CO Mod<M> z{};RE z;}TE <uint M> IN CO Mod<M>& Mod<M>::one()NE{ST CE CO Mod<M> o{DeRP(1)};RE o;}TE <uint M> TE <TY T> CE Mod<M>& Mod<M>::Ref(T&& n)NE{RE *TH;}TE <uint M> CE Mod<M> Twice(CO Mod<M>& n)NE{RE MO(Mod<M>(n).Double());}TE <uint M> CE Mod<M> Half(CO Mod<M>& n)NE{RE MO(Mod<M>(n).Halve());}TE <uint M> IN Mod<M> Inverse(CO Mod<M>& n){RE MO(Mod<M>(n).Invert());}TE <uint M> CE Mod<M> Inverse_COrexpr(CRUI n)NE{RE MO(Mod<M>::DeRP(RS<M>(n)).NonNegativePW(M - 2));}TE <uint M,TY T> CE Mod<M> PW(Mod<M> n,T EX){RE MO(n.PW(EX));}TE <TY T>CE Mod<2> PW(Mod<2> n,const T& p){RE p == 0?Mod<2>::one():move(n);}TE <uint M> CE VO swap(Mod<M>& n0,Mod<M>& n1)NE{n0.swap(n1);}TE <uint M> IN string to_string(CO Mod<M>& n)NE{RE to_string(n.RP())+ " + MZ";}TE<uint M,CL Traits> IN basic_ostream<char,Traits>& OP<<(basic_ostream<char,Traits>& os,CO Mod<M>& n){RE os << n.RP();}

// AAA 常設ライブラリは以上に挿入する。

#define INCLUDE_LIBRARY
#include __FILE__

#endif // INCLUDE_LIBRARY

#endif // INCLUDE_SUB

#endif // INCLUDE_MAIN
0