結果
| 問題 | No.3404 形式群法則 |
| コンテスト | |
| ユーザー |
👑 |
| 提出日時 | 2023-10-14 02:36:00 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 259 ms / 2,000 ms |
| コード長 | 8,346 bytes |
| 記録 | |
| コンパイル時間 | 9,685 ms |
| コンパイル使用メモリ | 243,236 KB |
| 実行使用メモリ | 7,848 KB |
| 最終ジャッジ日時 | 2025-12-10 23:30:31 |
| 合計ジャッジ時間 | 12,053 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 25 |
ソースコード
#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 <bits/stdc++.h>
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<decltype( VAR )>
#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 <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... ); }
// デバッグ用
#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<ll> Convolution( const vector<ll>& f , const vector<ll>& g , const uint& N , const ll& P )
{
vector<ll> 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<ll> Inverse( const vector<ll>& f , const uint& N , const ll& P )
{
uint power_minus = 0;
vector<ll> 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<ll> 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<ll> Composite( const vector<ll>& f , const vector<ll>& g , const uint& N , const ll& P )
{
if( N == 0 ){
return f;
}
const uint H = sqrt( N );
const uint K = N / H;
vector<vector<ll> > g_power( K < 2 ? 2 : K );
g_power[0] = vector<ll>( 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<vector<ll> > g_power2( H + 1 );
g_power2[0] = vector<ll>( 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<ll> fg( N + 1 );
vector<ll> 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<ll>( 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<ll> 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<ll> arctan( N + 1 );
FOREQ( d , 1 , N ){
arctan[d] = d % 2 == 0 ? 0 : d % 4 == 1 ? inv[d] : P - inv[d];
}
vector<ll> sin( N + 1 );
vector<ll> cos( N + 1 );
FOREQ( d , 0 , N ){
( d % 2 == 0 ? cos : sin )[d] = d % 4 < 2 ? fact_inv[d] : P - fact_inv[d];
}
vector<ll> 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);