// 入力制約/フォーマットチェック
#ifndef INCLUDE_MODE
#define INCLUDE_MODE
// #define REACTIVE
#define USE_GETLINE
#endif
#ifdef INCLUDE_MAIN
void Solve()
{
// 入力制約と入力形式をテストケースが満たしているか確認。
CEXPR( int , p , 1009 );
CEXPR( int , bound_M , int(4e5)-1 );
CEXPR( int , bound_N , int(2e3)-1 );
GETLINE_COUNT( MN_str , 2 , ' ' );
STOI( MN_str , M , 0 , bound_M );
STOI( MN_str , N , 0 , bound_N );
GETLINE_COUNT( K_str , M + 1 , ' ' );
STOI_A( K_str , 0 , M + 1 , K , 0 , p - 1 );
assert( K[M] != 0 );
GETLINE_COUNT( A_str , N + 1 , ' ' );
STOI_A( A_str , 0 , N + 1 , A_int , 0 , p - 1 );
// pが素数であることを確認。
FOR( i , 2 , p ){
assert( p % i != 0 );
}
// 以下普通に解く。
using T = Mod
;
vector A( N + 1 );
FOREQ( i , 0 , N ){
A[i] = A_int[i];
}
auto PolynomialMultiplication = [&]( const vector& a , const vector& b ){
vector answer( N + 1 );
FOREQ( i , 0 , N ){
FOREQ( j , 0 , N - i ){
answer[i+j] += a[i] * b[j];
}
}
return answer;
};
auto PolynomialPower = [&]( const vector& a , int n ){
vector answer( N + 1 );
vector a_power = a;
answer[0] = 1;
while( n > 0 ){
( n & 1 ) == 1 ? answer = PolynomialMultiplication( answer , a_power ) : answer;
a_power = PolynomialMultiplication( a_power , a_power );
n >>= 1;
}
return answer;
};
vector p_power( M + 1 , N + 1 );
vector> A_power( M + 1 );
p_power[0] = 1;
int exponent = 0;
FOREQ( m , 0 , M ){
if( p_power[m] <= N ){
A_power[m] = PolynomialPower( A , K[m] );
if( m < M ){
p_power[m+1] = p_power[m] * p;
}
} else {
exponent += K[m];
}
}
vector answer( N + 1 , 0 );
answer[0] = 1;
FOREQ( m , 0 , M ){
if( N < p_power[m] ){
break;
}
vector nanswer( N + 1 );
FOREQ( i , 0 , N ){
int j_max = ( N - i ) / p_power[m];
FOREQ( j , 0 , j_max ){
nanswer[i+j*p_power[m]] += answer[i] * A_power[m][j];
}
}
answer = move( nanswer );
}
RETURN( answer *= Power( A[0] , exponent ) );
}
REPEAT_MAIN(1);
#else // INCLUDE_MAIN
#ifdef INCLUDE_LIBRARY
// https://github.com/p-adic/cpp
// VVV ライブラリは以下に挿入する。redefinitionを避けるため圧縮元はincludeしない。
/* 圧縮用 */
#define TE template
#define TY typename
#define US using
#define ST static
#define AS assert
#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 LE length
#define PW Power
#define MO move
#define TH this
#define CRI CO int&
#define CRUI CO uint&
#define CRL CO ll&
#define VI virtual
#define IS basic_istream
#define OS basic_ostream
#define ST_AS static_assert
#define reMO_CO remove_const
#define is_COructible_v is_constructible_v
#define rBE rbegin
/* ConstexprModulo (7KB)*/
CEXPR(uint,P,998244353);
#define RP Represent
#define DeRP Derepresent
TE CE INT Residue(INT n)NE{RE MO(n < 0?((((++n)*= -1)%= M)*= -1)+= M - 1:n < INT(M)?n:n %= M);}TE CE INT& ResidueP(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 CL Mod;TE CL COantsForMod{PU:COantsForMod()= delete;ST CE CO uint g_memory_bound = 1e6;ST CE CO uint g_memory_LE = M < g_memory_bound?M:g_memory_bound;ST CE uint g_M_minus = M - 1;ST CE int g_order_minus_1 = M - 2;ST CE int g_order_minus_1_neg = -g_order_minus_1;};
#define SFINAE_FOR_MOD enable_if_t>>*
#define DC_OF_CM_FOR_MOD(OPR)CE bool OP OPR(CO Mod& n)CO NE
#define DC_OF_AR_FOR_MOD(OPR,EX)CE Mod OP OPR(Mod n)CO EX;
#define DF_OF_CM_FOR_MOD(OPR)TE CE bool Mod::OP OPR(CO Mod& n)CO NE{RE m_n OPR n.m_n;}
#define DF_OF_AR_FOR_MOD(OPR,EX,LEFT,OPR2)TE CE Mod Mod::OP OPR(Mod n)CO EX{RE MO(LEFT OPR2 ## = *TH);}TE CE Mod OP OPR(T n0,CO Mod& n1)EX{RE MO(Mod(MO(n0))OPR ## = n1);}
TE CL Mod{PU:uint m_n;CE Mod()NE;CE Mod(CO Mod& n)NE;CE Mod(Mod&& n)NE;TE CE Mod(T n)NE;CE Mod& OP=(Mod n)NE;CE Mod& OP+=(CO Mod& n)NE;CE Mod& OP-=(CO Mod& n)NE;CE Mod& OP*=(CO Mod& n)NE;IN Mod& OP/=(Mod n);TE CE Mod& OP<<=(INT n);TE CE Mod& OP>>=(INT n);CE Mod& OP++()NE;CE Mod OP++(int)NE;CE Mod& OP--()NE;CE Mod 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(+,NE);DC_OF_AR_FOR_MOD(-,NE);DC_OF_AR_FOR_MOD(*,NE);DC_OF_AR_FOR_MOD(/,);TE CE Mod OP^(INT EX)CO;TE CE Mod OP<<(INT n)CO;TE CE Mod OP>>(INT n)CO;CE Mod OP-()CO NE;CE Mod& SignInvert()NE;IN Mod& Invert();TE CE Mod& PW(INT EX);CE VO swap(Mod& n)NE;CE CRUI RP()CO NE;ST CE Mod DeRP(uint n)NE;ST IN CO Mod& Inverse(CRUI n);ST IN CO Mod& Factorial(CRUI n);ST IN CO Mod& FactorialInverse(CRUI n);ST IN Mod Combination(CRUI n,CRUI i);ST IN CO Mod& zero()NE;ST IN CO Mod& one()NE;ST IN CE uint GetModulo()NE;TE CE Mod& PositivePW(INT EX)NE;TE CE Mod& NonNegativePW(INT EX)NE;US COants = COantsForMod;};
US MP = Mod;
TE CE Mod::Mod()NE:m_n(){}TE CE Mod::Mod(CO Mod& n)NE:m_n(n.m_n){}TE CE Mod::Mod(Mod&& n)NE:m_n(MO(n.m_n)){}TE TE CE Mod::Mod(T n)NE:m_n(Residue(MO(n))){}TE CE Mod& Mod::OP=(Mod n)NE{m_n = MO(n.m_n);RE *TH;}TE CE Mod& Mod::OP+=(CO Mod& n)NE{(m_n += n.m_n)< M?m_n:m_n -= M;RE *TH;}TE CE Mod& Mod::OP-=(CO Mod& n)NE{m_n < n.m_n?(m_n += M)-= n.m_n:m_n -= n.m_n;RE *TH;}TE CE Mod& Mod::OP*=(CO Mod& n)NE{m_n = MO(ull(m_n)* n.m_n)% M;RE *TH;}TE <> CE MP& MP::OP*=(CO MP& n)NE{ull m_n_copy = m_n;m_n = MO((m_n_copy *= n.m_n)< P?m_n_copy:ResidueP(m_n_copy));RE *TH;}TE IN Mod& Mod::OP/=(Mod n){RE OP*=(n.Invert());}TE TE CE Mod& Mod::OP<<=(INT n){AS(n >= 0);RE *TH *= Mod(2).NonNegativePW(MO(n));}TE TE CE Mod& Mod::OP>>=(INT n){AS(n >=0);WH(n-- > 0){((m_n & 1)== 0?m_n:m_n += M)>>= 1;}RE *TH;}TE CE Mod& Mod::OP++()NE{m_n < COants::g_M_minus?++m_n:m_n = 0;RE *TH;}TE CE Mod Mod::OP++(int)NE{Mod n{*TH};OP++();RE n;}TE CE Mod& Mod::OP--()NE{m_n == 0?m_n = COants::g_M_minus:--m_n;RE *TH;}TE CE Mod Mod::OP--(int)NE{Mod 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(+,NE,n,+);DF_OF_AR_FOR_MOD(-,NE,n.SignInvert(),+);DF_OF_AR_FOR_MOD(*,NE,n,*);DF_OF_AR_FOR_MOD(/,,n.Invert(),*);TE TE CE Mod Mod::OP^(INT EX)CO{RE MO(Mod(*TH).PW(MO(EX)));}TE TE CE Mod Mod::OP<<(INT n)CO{RE MO(Mod(*TH)<<= MO(n));}TE TE CE Mod Mod::OP>>(INT n)CO{RE MO(Mod(*TH)>>= MO(n));}TE CE Mod Mod::OP-()CO NE{RE MO(Mod(*TH).SignInvert());}TE CE Mod& Mod::SignInvert()NE{m_n > 0?m_n = M - m_n:m_n;RE *TH;}TE IN Mod& Mod::Invert(){AS(m_n != 0);uint m_n_neg;RE m_n < COants::g_memory_LE?(m_n = Inverse(m_n).m_n,*TH):((m_n_neg = M - m_n)< COants::g_memory_LE)?(m_n = M - Inverse(m_n_neg).m_n,*TH):NonNegativePW(COants::g_order_minus_1);}TE TE CE Mod& Mod::PositivePW(INT EX)NE{Mod PW{*TH};EX--;WH(EX != 0){(EX & 1)== 1?*TH *= PW:*TH;EX >>= 1;PW *= PW;}RE *TH;}TE TE CE Mod& Mod::NonNegativePW(INT EX)NE{RE EX == 0?(m_n = 1,*TH):PositivePW(MO(EX));}TE TE CE Mod& Mod::PW(INT EX){bool neg = EX < 0;AS(!(neg && m_n == 0));RE neg?PositivePW(ll(MO(EX %= COants::g_M_minus))* COants::g_order_minus_1_neg %COants::g_M_minus):NonNegativePW(MO(EX));}TE CE VO Mod::swap(Mod& n)NE{std::swap(m_n,n.m_n);}TE IN CO Mod& Mod::Inverse(CRUI n){AS(n < M);ST VE> memory ={zero(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory.push_back(DeRP(M - memory[M % LE_curr].m_n * ull(M / LE_curr)% M));LE_curr++;}RE memory[n];}TE IN CO Mod& Mod::Factorial(CRUI n){if(M <= n){RE zero();}ST VE> memory ={one(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory.push_back(memory[LE_curr - 1]* LE_curr);LE_curr++;}RE memory[n];}TE IN CO Mod& Mod::FactorialInverse(CRUI n){ST VE> memory ={one(),one()};ST uint LE_curr = 2;WH(LE_curr <= n){memory.push_back(memory[LE_curr - 1]* Inverse(LE_curr));LE_curr++;}RE memory[n];}TE IN Mod Mod::Combination(CRUI n,CRUI i){RE i <= n?Factorial(n)* FactorialInverse(i)* FactorialInverse(n - i):zero();}TE CE CRUI Mod::RP()CO NE{RE m_n;}TE CE Mod Mod::DeRP(uint n)NE{Mod n_copy{};n_copy.m_n = MO(n);RE n_copy;}TE IN CO Mod& Mod::zero()NE{ST CE CO Mod z{};RE z;}TE IN CO Mod& Mod::one()NE{ST CE CO Mod o{1};RE o;}TE IN CE uint Mod::GetModulo()NE{RE M;}TE IN Mod Inverse(CO Mod& n){RE MO(Mod(n).Invert());}TE CE Mod PW(Mod n,INT EX){RE MO(n.PW(MO(EX)));}TE CE VO swap(Mod& n0,Mod& n1)NE{n0.swap(n1);}TE IN string to_string(CO Mod& n)NE{RE to_string(n.RP())+ " + " + to_string(M)+ "Z";}TE IN IS& OP>>(IS& is,Mod& n){ll m;is >> m;n = m;RE is;}TE IN OS& OP<<(OS& os,CO Mod& n){RE os << n.RP();}
// AAA ライブラリは以上に挿入する。
#define INCLUDE_MAIN
#include __FILE__
#else // INCLUDE_LIBRARY
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define DEXPR( LL , BOUND , VALUE1 , VALUE2 ) CEXPR( LL , BOUND , VALUE2 )
#define SIGNAL signal( SIGABRT , &AlertAbort );
#define ASSERT( A , MIN , MAX ) CERR( "ASSERTチェック: " , ( MIN ) , ( ( MIN ) <= A ? "<=" : ">" ) , A , ( A <= ( MAX ) ? "<=" : ">" ) , ( MAX ) ); assert( ( MIN ) <= A && A <= ( MAX ) )
#define COUT( ... ) VariadicCout( cout << "出力:" , __VA_ARGS__ ) << endl
#define COUTNS( ... ) VariadicCoutNonSep( cout , __VA_ARGS__ ) << flush
#define CERR( ... ) VariadicCout( cerr , __VA_ARGS__ ) << endl
#define CERRNS( ... ) VariadicCout( cerr , __VA_ARGS__ ) << flush
#define COUT_A( A , N ) OUTPUT_ARRAY( cout << "出力:" , A , N ) << endl
#define CERR_A( A , N ) OUTPUT_ARRAY( cerr , A , N ) << endl
int exec_mode = 0;
#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 , VALUE1 , VALUE2 ) CEXPR( LL , BOUND , VALUE1 )
#define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) )
#define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << ENDL
#define COUTNS( ... ) VariadicCoutNonSep( cout , __VA_ARGS__ )
#define CERR( ... )
#define CERRNS( ... )
#define COUT_A( A , N ) OUTPUT_ARRAY( cout , A , N ) << ENDL
#define CERR_A( A , N )
#endif
#ifdef REACTIVE
#ifdef DEBUG
#define RSET( A , ... ) A = __VA_ARGS__
#else
#define RSET( A , ... ) cin >> A
#endif
#define RCIN( LL , A , ... ) LL A; RSET( A , __VA_ARGS__ )
#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 , ... ) string __VA_ARGS__; VariadicGetline( cin , SEPARATOR , __VA_ARGS__ )
#define GETLINE( ... ) GETLINE_SEPARATE( '\n' , __VA_ARGS__ )
#else
#define SET_LL( A ) cin >> A
#define CIN( LL , ... ) LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ )
#define SET_A( I , N , ... ) VariadicResize( N + I , __VA_ARGS__ ); FOR( VARIABLE_FOR_SET_A , 0 , N ){ VariadicSet( cin , VARIABLE_FOR_SET_A + I , __VA_ARGS__ ); }
#define CIN_A( LL , I , N , ... ) vector __VA_ARGS__; SET_A( I , N , __VA_ARGS__ )
#define CIN_AA( LL , I0 , N0 , I1 , N1 , VAR ) vector> VAR( N0 + I0 ); FOR( VARIABLE_FOR_CIN_AA , 0 , N0 ){ SET_A( I1 , N1 , VAR[VARIABLE_FOR_CIN_AA + I0] ); }
#endif
#include
using namespace std;
#define REPEAT_MAIN( BOUND ) int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr ); SIGNAL; CEXPR( int , bound_test_case_num , BOUND ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ CERR( "テストケースの個数を入力してください。" ); SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } FOR( test_case , 0 , test_case_num ){ if constexpr( bound_test_case_num > 1 ){ CERR( "testcase" , test_case , ":" ); } Solve(); CERR( "" ); } CHECK_REDUNDANT_INPUT; }
#define START_WATCH chrono::system_clock::time_point watch = chrono::system_clock::now()
#define CURRENT_TIME static_cast( chrono::duration_cast( chrono::system_clock::now() - watch ).count() / 1000.0 )
#define CHECK_WATCH( TL_MS ) ( CURRENT_TIME < TL_MS - 100.0 )
#define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE
#define SET_ASSERT( A , MIN , MAX ) SET_LL( A ); ASSERT( A , MIN , MAX )
#define SET_A_ASSERT( I , N , A , MIN , MAX ) FOR( VARIABLE_FOR_SET_A , 0 , N ){ SET_ASSERT( A[VARIABLE_FOR_SET_A + I] , MIN , MAX ); }
#define SET_AA_ASSERT( I0 , N0 , I1 , N1 , A , MIN , MAX ) FOR( VARIABLE_FOR_SET_AA0 , 0 , N0 ){ FOR( VARIABLE_FOR_SET_AA1 , 0 , N1 ){ SET_ASSERT( A[VARIABLE_FOR_SET_AA0 + I0][VARIABLE_FOR_SET_AA1 + I1] , MIN , MAX ); } }
#define CIN_ASSERT( A , MIN , MAX ) decldecay_t( MAX ) A; SET_ASSERT( A , MIN , MAX )
#define CIN_A_ASSERT( I , N , A , MIN , MAX ) vector A( N + I ); SET_A_ASSERT( I , N , A , MIN , MAX )
#define CIN_AA_ASSERT( I0 , N0 , I1 , N1 , A , MIN , MAX ) vector A( N0 + I0 , vector( N1 + I1 ) ); SET_AA_ASSERT( I0 , N0 , I1 , N1 , A , MIN , MAX )
#define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( decldecay_t( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ )
#define FOREQ( VAR , INITIAL , FINAL ) for( decldecay_t( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ )
#define FOREQINV( VAR , INITIAL , FINAL ) for( decldecay_t( INITIAL ) VAR = INITIAL ; VAR + 1 > FINAL ; VAR -- )
#define ITR( ARRAY ) auto begin_ ## ARRAY = ARRAY .BE() , itr_ ## ARRAY = begin_ ## ARRAY , end_ ## ARRAY = ARRAY .EN()
#define FOR_ITR( ARRAY ) for( ITR( ARRAY ) , itr = itr_ ## ARRAY ; itr_ ## ARRAY != end_ ## ARRAY ; itr_ ## ARRAY ++ , itr++ )
#define RUN( ARRAY , ... ) for( auto&& __VA_ARGS__ : ARRAY )
#define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT , 0 , HOW_MANY_TIMES )
#define SET_PRECISION( DECIMAL_DIGITS ) cout << fixed << setprecision( DECIMAL_DIGITS )
#define RETURN( ... ) COUT( __VA_ARGS__ ); return
// 型のエイリアス
#define decldecay_t( VAR ) decay_t
template using ret_t = decltype( declval()( declval()... ) );
template using inner_t = typename T::type;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using lld = __float128;
template using T2 = pair;
template using T3 = tuple;
template using T4 = tuple;
using path = pair;
/* VVV 常設ライブラリの非圧縮版は以下に挿入する。*/
// Random
ll GetRand( const int& Rand_min , const int& Rand_max ) { assert( Rand_min <= Rand_max ); ll answer = time( NULL ); return answer * rand() % ( Rand_max + 1 - Rand_min ) + Rand_min; }
// Set
#define DECLARATION_OF_HASH( ... ) \
struct hash<__VA_ARGS__> \
{ \
\
inline size_t operator()( const __VA_ARGS__& n ) const; \
\
}; \
class is_ordered
{
private:
is_ordered() = delete;
template static constexpr auto Check( const T& t ) -> decltype( t < t , true_type() );
static constexpr false_type Check( ... );
public:
template static constexpr const bool value = is_same_v< decltype( Check( declval() ) ) , true_type >;
};
template
using Set = conditional_t>,unordered_set,conditional_t,set,void>>;
// Tuple
#define DECLARATION_OF_ARITHMETIC_FOR_TUPLE( OPR ) \
template typename V> inline auto operator OPR ## =( V& t0 , const V& t1 ) -> decltype( ( get<0>( t0 ) , t0 ) )&; \
template