#ifdef DEBUG #define _GLIBCXX_DEBUG #define SIGNAL signal( SIGABRT , &AlertAbort ); #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 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 SIGNAL #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , VALUE ) #define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) ) #define CERR( ... ) #define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << "\n" #define CERR_A( A , N ) #define COUT_A( A , N ) OUTPUT_ARRAY( cout , A , N ) << "\n" #define CERR_ITR( A ) #define COUT_ITR( A ) OUTPUT_ITR( cout , A ) << "\n" #endif #include using namespace std; using uint = unsigned int; using ll = long long; #define REPEAT_MAIN( BOUND ) int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr ); SIGNAL; DEXPR( int , bound_test_case_num , BOUND , min( BOUND , 100 ) ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } REPEAT( test_case_num ){ if constexpr( bound_test_case_num > 1 ){ CERR( "testcase " , VARIABLE_FOR_REPEAT_test_case_num , ":" ); } Solve(); CERR( "" ); } } #define TYPE_OF( VAR ) decay_t #define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE #define CIN( LL , ... ) LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ ) #define SET_ASSERT( A , MIN , MAX ) cin >> A; ASSERT( A , MIN , MAX ) #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 REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT_ ## HOW_MANY_TIMES , 0 , HOW_MANY_TIMES ) // 入出力用 template inline basic_istream& VariadicCin( basic_istream& is ) { return is; } template inline basic_istream& VariadicCin( basic_istream& is , Arg& arg , ARGS&... args ) { return VariadicCin( is >> arg , args... ); } template inline basic_istream& VariadicGetline( basic_istream& is , const char& separator ) { return is; } template inline basic_istream& VariadicGetline( basic_istream& is , const char& separator , Arg& arg , ARGS&... args ) { return VariadicGetline( getline( is , arg , separator ) , separator , args... ); } template inline basic_ostream& VariadicCout( basic_ostream& os , const Arg& arg ) { return os << arg; } template inline basic_ostream& VariadicCout( basic_ostream& os , const Arg1& arg1 , const Arg2& arg2 , const ARGS&... args ) { return VariadicCout( os << arg1 << " " , arg2 , args... ); } // デバッグ用 #ifdef DEBUG inline void AlertAbort( int n ) { CERR( "abort関数が呼ばれました。assertマクロのメッセージが出力されていない場合はオーバーフローの有無を確認をしてください。" ); } void AutoCheck( bool& auto_checked ); #endif #define FACTORIAL_MOD( ANSWER , ANSWER_INV , INVERSE , MAX_INDEX , CONSTEXPR_LENGTH , MODULO ) \ ll ANSWER[CONSTEXPR_LENGTH]; \ ll ANSWER_INV[CONSTEXPR_LENGTH]; \ ll INVERSE[CONSTEXPR_LENGTH]; \ { \ ll VARIABLE_FOR_PRODUCT_FOR_FACTORIAL = 1; \ ANSWER[0] = VARIABLE_FOR_PRODUCT_FOR_FACTORIAL; \ FOREQ( i , 1 , MAX_INDEX ){ \ ANSWER[i] = ( VARIABLE_FOR_PRODUCT_FOR_FACTORIAL *= i ) %= ( MODULO ); \ } \ ANSWER_INV[0] = ANSWER_INV[1] = INVERSE[1] = VARIABLE_FOR_PRODUCT_FOR_FACTORIAL = 1; \ FOREQ( i , 2 , MAX_INDEX ){ \ ANSWER_INV[i] = ( VARIABLE_FOR_PRODUCT_FOR_FACTORIAL *= INVERSE[i] = ( MODULO ) - ( ( ( ( MODULO ) / i ) * INVERSE[ ( MODULO ) % i ] ) % ( MODULO ) ) ) %= ( MODULO ); \ } \ } \ vector Convolution( const vector& f , const vector& g , const uint& N , const ll& P ) { vector fg( N + 1 ); uint g_deg = g.size(); g_deg == 0 ? g_deg : g_deg -= 1; for( uint d = 0 ; d <= N ; d++ ){ const uint i_max = min( d , g_deg ); for( uint i = 0 ; i <= i_max ; i++ ){ ( fg[d] += f[d-i] * g[i] ) %= P; } } return fg; } vector Inverse( const vector& f , const uint& N , const ll& P ) { uint power_minus = 0; vector f_inv( power_minus + 1 ); // f[0] == 1の場合のみサポート。 // そうでない場合は1の代わりにf[0]の逆元を代入。 f_inv[0] = 1; while( power_minus < N ){ power_minus = ( power_minus << 1 ) | 1; f_inv.resize( power_minus + 1 ); vector temp = Convolution( f_inv , f , power_minus , P ); ( temp[0] = ( P == 2 ? 0 : 2 ) - temp[0] ) < 0 ? temp[0] += P : 0; for( uint d = 1 ; d <= power_minus ; d++ ){ temp[d] > 0 ? temp[d] = P - temp[d] : 0; } f_inv = Convolution( f_inv , temp , power_minus , P ); } f_inv.resize( N + 1 ); return f_inv; } vector Composite( const vector& f , const vector& g , const uint& N , const ll& P ) { if( N == 0 ){ return f; } const uint H = sqrt( N ); const uint K = N / H; vector > g_power( K < 2 ? 2 : K ); g_power[0] = vector( N + 1 ); g_power[0][0] = 1; g_power[1] = g; for( uint k = 2 ; k < K ; k++ ){ g_power[k] = Convolution( g_power[k-1] , g_power[1] , N , P ); } vector > g_power2( H + 1 ); g_power2[0] = vector( N + 1 ); g_power2[0][0] = 1; g_power2[1] = Convolution( g_power[K-1] , g_power[1] , N , P ); for( uint h = 2 ; h <= H ; h++ ){ g_power2[h] = Convolution( g_power2[h-1] , g_power2[1] , N , P ); } uint k = 0; uint h = 0; uint n_max = N; vector fg( N + 1 ); vector fg_h( N + 1 ); for( uint d = 0 ; d <= N ; d++ ){ for( uint n = k ; n <= n_max ; n++ ){ ( fg_h[n] += f[d] * g_power[k][n] ) %= P; } if( ++k == K || d == N ){ fg_h = Convolution( fg_h , g_power2[h] , N , P ); for( uint n = 0 ; n <= N ; n++ ){ ( fg[n] += fg_h[n] ) < P ? 0 : fg[n] -= P; } k = 0; h++; n_max -= K; fg_h = vector( N + 1 ); } } return fg; } inline void Solve() { CEXPR( uint , bound_N , 1000 ); // 0が3個 CIN_ASSERT( N , 1 , bound_N ); CEXPR( ll , bound_M , 1000000000000000000 ); // 0が18個 CIN_ASSERT( M , 1 , bound_M ); CEXPR( ll , bound_P , 1000000000 ); // 0が9個 CIN_ASSERT( P , N + 1 , bound_P ); CEXPR( ll , bound_Ad , 1000000000000000000 ); // 0が18個 vector A( N + 1 ); FOREQ( d , 1 , N ){ CIN_ASSERT( Ad , 0 , bound_Ad ); A[d] = move( Ad %= P ); } FACTORIAL_MOD( fact , fact_inv , inv , N , bound_N + 1 , P ); vector arctan( N + 1 ); FOREQ( d , 1 , N ){ arctan[d] = d % 2 == 0 ? 0 : d % 4 == 1 ? inv[d] : P - inv[d]; } vector sin( N + 1 ); vector cos( N + 1 ); FOREQ( d , 0 , N ){ ( d % 2 == 0 ? cos : sin )[d] = d % 4 < 2 ? fact_inv[d] : P - fact_inv[d]; } vector tan = Convolution( sin , Inverse( cos , N , P ) , N , P ); A = Composite( arctan , A , N , P ); M %= P; FOREQ( d , 1 , N ){ ( A[d] *= M ) %= P; } A = Composite( tan , A , N , P ); FOREQ( d , 1 , N ){ cout << A[d] << " \n"[d==N]; } } REPEAT_MAIN(1);