#line 2 "fps/arbitrary-fps.hpp"
#include <cstdlib>
#line 2 "ntt/arbitrary-ntt.hpp"
#include <algorithm>
#include <cstdint>
#include <vector>
using namespace std ;
#line 2 "modint/montgomery-modint.hpp"
#line 4 "modint/montgomery-modint.hpp"
#include <iostream>
template < uint32_t mod >
struct LazyMontgomeryModInt {
using mint = LazyMontgomeryModInt ;
using i32 = int32_t ;
using u32 = uint32_t ;
using u64 = uint64_t ;
static constexpr u32 get_r () {
u32 ret = mod ;
for ( i32 i = 0 ; i < 4 ; ++ i ) ret *= 2 - mod * ret ;
return ret ;
}
static constexpr u32 r = get_r ();
static constexpr u32 n2 = - u64 ( mod ) % mod ;
static_assert ( mod < ( 1 << 30 ), "invalid, mod >= 2 ^ 30" );
static_assert (( mod & 1 ) == 1 , "invalid, mod % 2 == 0" );
static_assert ( r * mod == 1 , "this code has bugs." );
u32 a ;
constexpr LazyMontgomeryModInt () : a ( 0 ) {}
constexpr LazyMontgomeryModInt ( const int64_t & b )
: a ( reduce ( u64 ( b % mod + mod ) * n2 )){};
static constexpr u32 reduce ( const u64 & b ) {
return ( b + u64 ( u32 ( b ) * u32 ( - r )) * mod ) >> 32 ;
}
constexpr mint & operator += ( const mint & b ) {
if ( i32 ( a += b . a - 2 * mod ) < 0 ) a += 2 * mod ;
return * this ;
}
constexpr mint & operator -= ( const mint & b ) {
if ( i32 ( a -= b . a ) < 0 ) a += 2 * mod ;
return * this ;
}
constexpr mint & operator *= ( const mint & b ) {
a = reduce ( u64 ( a ) * b . a );
return * this ;
}
constexpr mint & operator /= ( const mint & b ) {
* this *= b . inverse ();
return * this ;
}
constexpr mint operator + ( const mint & b ) const { return mint ( * this ) += b ; }
constexpr mint operator - ( const mint & b ) const { return mint ( * this ) -= b ; }
constexpr mint operator * ( const mint & b ) const { return mint ( * this ) *= b ; }
constexpr mint operator / ( const mint & b ) const { return mint ( * this ) /= b ; }
constexpr bool operator == ( const mint & b ) const {
return ( a >= mod ? a - mod : a ) == ( b . a >= mod ? b . a - mod : b . a );
}
constexpr bool operator != ( const mint & b ) const {
return ( a >= mod ? a - mod : a ) != ( b . a >= mod ? b . a - mod : b . a );
}
constexpr mint operator - () const { return mint () - mint ( * this ); }
constexpr mint operator + () const { return mint ( * this ); }
constexpr mint pow ( u64 n ) const {
mint ret ( 1 ), mul ( * this );
while ( n > 0 ) {
if ( n & 1 ) ret *= mul ;
mul *= mul ;
n >>= 1 ;
}
return ret ;
}
constexpr mint inverse () const {
int x = get (), y = mod , u = 1 , v = 0 , t = 0 , tmp = 0 ;
while ( y > 0 ) {
t = x / y ;
x -= t * y , u -= t * v ;
tmp = x , x = y , y = tmp ;
tmp = u , u = v , v = tmp ;
}
return mint { u };
}
friend std :: ostream & operator << ( std :: ostream & os , const mint & b ) {
return os << b . get ();
}
friend std :: istream & operator >> ( std :: istream & is , mint & b ) {
int64_t t ;
is >> t ;
b = LazyMontgomeryModInt < mod > ( t );
return ( is );
}
constexpr u32 get () const {
u32 ret = reduce ( a );
return ret >= mod ? ret - mod : ret ;
}
static constexpr u32 get_mod () { return mod ; }
};
#line 2 "ntt/ntt.hpp"
#line 5 "ntt/ntt.hpp"
#include <iterator>
#line 7 "ntt/ntt.hpp"
using namespace std ;
template < typename mint >
struct NTT {
static constexpr uint32_t get_pr () {
uint32_t _mod = mint :: get_mod ();
using u64 = uint64_t ;
u64 ds [ 32 ] = {};
int idx = 0 ;
u64 m = _mod - 1 ;
for ( u64 i = 2 ; i * i <= m ; ++ i ) {
if ( m % i == 0 ) {
ds [ idx ++ ] = i ;
while ( m % i == 0 ) m /= i ;
}
}
if ( m != 1 ) ds [ idx ++ ] = m ;
uint32_t _pr = 2 ;
while ( 1 ) {
int flg = 1 ;
for ( int i = 0 ; i < idx ; ++ i ) {
u64 a = _pr , b = ( _mod - 1 ) / ds [ i ], r = 1 ;
while ( b ) {
if ( b & 1 ) r = r * a % _mod ;
a = a * a % _mod ;
b >>= 1 ;
}
if ( r == 1 ) {
flg = 0 ;
break ;
}
}
if ( flg == 1 ) break ;
++ _pr ;
}
return _pr ;
};
static constexpr uint32_t mod = mint :: get_mod ();
static constexpr uint32_t pr = get_pr ();
static constexpr int level = __builtin_ctzll ( mod - 1 );
mint dw [ level ], dy [ level ];
void setwy ( int k ) {
mint w [ level ], y [ level ];
w [ k - 1 ] = mint ( pr ). pow (( mod - 1 ) / ( 1 << k ));
y [ k - 1 ] = w [ k - 1 ]. inverse ();
for ( int i = k - 2 ; i > 0 ; -- i )
w [ i ] = w [ i + 1 ] * w [ i + 1 ], y [ i ] = y [ i + 1 ] * y [ i + 1 ];
dw [ 1 ] = w [ 1 ], dy [ 1 ] = y [ 1 ], dw [ 2 ] = w [ 2 ], dy [ 2 ] = y [ 2 ];
for ( int i = 3 ; i < k ; ++ i ) {
dw [ i ] = dw [ i - 1 ] * y [ i - 2 ] * w [ i ];
dy [ i ] = dy [ i - 1 ] * w [ i - 2 ] * y [ i ];
}
}
NTT () { setwy ( level ); }
void fft4 ( vector < mint > & a , int k ) {
if (( int ) a . size () <= 1 ) return ;
if ( k == 1 ) {
mint a1 = a [ 1 ];
a [ 1 ] = a [ 0 ] - a [ 1 ];
a [ 0 ] = a [ 0 ] + a1 ;
return ;
}
if ( k & 1 ) {
int v = 1 << ( k - 1 );
for ( int j = 0 ; j < v ; ++ j ) {
mint ajv = a [ j + v ];
a [ j + v ] = a [ j ] - ajv ;
a [ j ] += ajv ;
}
}
int u = 1 << ( 2 + ( k & 1 ));
int v = 1 << ( k - 2 - ( k & 1 ));
mint one = mint ( 1 );
mint imag = dw [ 1 ];
while ( v ) {
// jh = 0
{
int j0 = 0 ;
int j1 = v ;
int j2 = j1 + v ;
int j3 = j2 + v ;
for (; j0 < v ; ++ j0 , ++ j1 , ++ j2 , ++ j3 ) {
mint t0 = a [ j0 ], t1 = a [ j1 ], t2 = a [ j2 ], t3 = a [ j3 ];
mint t0p2 = t0 + t2 , t1p3 = t1 + t3 ;
mint t0m2 = t0 - t2 , t1m3 = ( t1 - t3 ) * imag ;
a [ j0 ] = t0p2 + t1p3 , a [ j1 ] = t0p2 - t1p3 ;
a [ j2 ] = t0m2 + t1m3 , a [ j3 ] = t0m2 - t1m3 ;
}
}
// jh >= 1
mint ww = one , xx = one * dw [ 2 ], wx = one ;
for ( int jh = 4 ; jh < u ;) {
ww = xx * xx , wx = ww * xx ;
int j0 = jh * v ;
int je = j0 + v ;
int j2 = je + v ;
for (; j0 < je ; ++ j0 , ++ j2 ) {
mint t0 = a [ j0 ], t1 = a [ j0 + v ] * xx , t2 = a [ j2 ] * ww ,
t3 = a [ j2 + v ] * wx ;
mint t0p2 = t0 + t2 , t1p3 = t1 + t3 ;
mint t0m2 = t0 - t2 , t1m3 = ( t1 - t3 ) * imag ;
a [ j0 ] = t0p2 + t1p3 , a [ j0 + v ] = t0p2 - t1p3 ;
a [ j2 ] = t0m2 + t1m3 , a [ j2 + v ] = t0m2 - t1m3 ;
}
xx *= dw [ __builtin_ctzll (( jh += 4 ))];
}
u <<= 2 ;
v >>= 2 ;
}
}
void ifft4 ( vector < mint > & a , int k ) {
if (( int ) a . size () <= 1 ) return ;
if ( k == 1 ) {
mint a1 = a [ 1 ];
a [ 1 ] = a [ 0 ] - a [ 1 ];
a [ 0 ] = a [ 0 ] + a1 ;
return ;
}
int u = 1 << ( k - 2 );
int v = 1 ;
mint one = mint ( 1 );
mint imag = dy [ 1 ];
while ( u ) {
// jh = 0
{
int j0 = 0 ;
int j1 = v ;
int j2 = v + v ;
int j3 = j2 + v ;
for (; j0 < v ; ++ j0 , ++ j1 , ++ j2 , ++ j3 ) {
mint t0 = a [ j0 ], t1 = a [ j1 ], t2 = a [ j2 ], t3 = a [ j3 ];
mint t0p1 = t0 + t1 , t2p3 = t2 + t3 ;
mint t0m1 = t0 - t1 , t2m3 = ( t2 - t3 ) * imag ;
a [ j0 ] = t0p1 + t2p3 , a [ j2 ] = t0p1 - t2p3 ;
a [ j1 ] = t0m1 + t2m3 , a [ j3 ] = t0m1 - t2m3 ;
}
}
// jh >= 1
mint ww = one , xx = one * dy [ 2 ], yy = one ;
u <<= 2 ;
for ( int jh = 4 ; jh < u ;) {
ww = xx * xx , yy = xx * imag ;
int j0 = jh * v ;
int je = j0 + v ;
int j2 = je + v ;
for (; j0 < je ; ++ j0 , ++ j2 ) {
mint t0 = a [ j0 ], t1 = a [ j0 + v ], t2 = a [ j2 ], t3 = a [ j2 + v ];
mint t0p1 = t0 + t1 , t2p3 = t2 + t3 ;
mint t0m1 = ( t0 - t1 ) * xx , t2m3 = ( t2 - t3 ) * yy ;
a [ j0 ] = t0p1 + t2p3 , a [ j2 ] = ( t0p1 - t2p3 ) * ww ;
a [ j0 + v ] = t0m1 + t2m3 , a [ j2 + v ] = ( t0m1 - t2m3 ) * ww ;
}
xx *= dy [ __builtin_ctzll ( jh += 4 )];
}
u >>= 4 ;
v <<= 2 ;
}
if ( k & 1 ) {
u = 1 << ( k - 1 );
for ( int j = 0 ; j < u ; ++ j ) {
mint ajv = a [ j ] - a [ j + u ];
a [ j ] += a [ j + u ];
a [ j + u ] = ajv ;
}
}
}
void ntt ( vector < mint > & a ) {
if (( int ) a . size () <= 1 ) return ;
fft4 ( a , __builtin_ctz ( a . size ()));
}
void intt ( vector < mint > & a ) {
if (( int ) a . size () <= 1 ) return ;
ifft4 ( a , __builtin_ctz ( a . size ()));
mint iv = mint ( a . size ()). inverse ();
for ( auto & x : a ) x *= iv ;
}
vector < mint > multiply ( const vector < mint > & a , const vector < mint > & b ) {
int l = a . size () + b . size () - 1 ;
if ( min < int > ( a . size (), b . size ()) <= 40 ) {
vector < mint > s ( l );
for ( int i = 0 ; i < ( int ) a . size (); ++ i )
for ( int j = 0 ; j < ( int ) b . size (); ++ j ) s [ i + j ] += a [ i ] * b [ j ];
return s ;
}
int k = 2 , M = 4 ;
while ( M < l ) M <<= 1 , ++ k ;
setwy ( k );
vector < mint > s ( M );
for ( int i = 0 ; i < ( int ) a . size (); ++ i ) s [ i ] = a [ i ];
fft4 ( s , k );
if ( a . size () == b . size () && a == b ) {
for ( int i = 0 ; i < M ; ++ i ) s [ i ] *= s [ i ];
} else {
vector < mint > t ( M );
for ( int i = 0 ; i < ( int ) b . size (); ++ i ) t [ i ] = b [ i ];
fft4 ( t , k );
for ( int i = 0 ; i < M ; ++ i ) s [ i ] *= t [ i ];
}
ifft4 ( s , k );
s . resize ( l );
mint invm = mint ( M ). inverse ();
for ( int i = 0 ; i < l ; ++ i ) s [ i ] *= invm ;
return s ;
}
void ntt_doubling ( vector < mint > & a ) {
int M = ( int ) a . size ();
auto b = a ;
intt ( b );
mint r = 1 , zeta = mint ( pr ). pow (( mint :: get_mod () - 1 ) / ( M << 1 ));
for ( int i = 0 ; i < M ; i ++ ) b [ i ] *= r , r *= zeta ;
ntt ( b );
copy ( begin ( b ), end ( b ), back_inserter ( a ));
}
};
#line 10 "ntt/arbitrary-ntt.hpp"
namespace ArbitraryNTT {
using i64 = int64_t ;
using u128 = __uint128_t ;
constexpr int32_t m0 = 167772161 ;
constexpr int32_t m1 = 469762049 ;
constexpr int32_t m2 = 754974721 ;
using mint0 = LazyMontgomeryModInt < m0 > ;
using mint1 = LazyMontgomeryModInt < m1 > ;
using mint2 = LazyMontgomeryModInt < m2 > ;
constexpr int r01 = mint1 ( m0 ). inverse (). get ();
constexpr int r02 = mint2 ( m0 ). inverse (). get ();
constexpr int r12 = mint2 ( m1 ). inverse (). get ();
constexpr int r02r12 = i64 ( r02 ) * r12 % m2 ;
constexpr i64 w1 = m0 ;
constexpr i64 w2 = i64 ( m0 ) * m1 ;
template < typename T , typename submint >
vector < submint > mul ( const vector < T > & a , const vector < T > & b ) {
static NTT < submint > ntt ;
vector < submint > s ( a . size ()), t ( b . size ());
for ( int i = 0 ; i < ( int ) a . size (); ++ i ) s [ i ] = i64 ( a [ i ] % submint :: get_mod ());
for ( int i = 0 ; i < ( int ) b . size (); ++ i ) t [ i ] = i64 ( b [ i ] % submint :: get_mod ());
return ntt . multiply ( s , t );
}
template < typename T >
vector < int > multiply ( const vector < T > & s , const vector < T > & t , int mod ) {
auto d0 = mul < T , mint0 > ( s , t );
auto d1 = mul < T , mint1 > ( s , t );
auto d2 = mul < T , mint2 > ( s , t );
int n = d0 . size ();
vector < int > ret ( n );
const int W1 = w1 % mod ;
const int W2 = w2 % mod ;
for ( int i = 0 ; i < n ; i ++ ) {
int n1 = d1 [ i ]. get (), n2 = d2 [ i ]. get (), a = d0 [ i ]. get ();
int b = i64 ( n1 + m1 - a ) * r01 % m1 ;
int c = ( i64 ( n2 + m2 - a ) * r02r12 + i64 ( m2 - b ) * r12 ) % m2 ;
ret [ i ] = ( i64 ( a ) + i64 ( b ) * W1 + i64 ( c ) * W2 ) % mod ;
}
return ret ;
}
template < typename mint >
vector < mint > multiply ( const vector < mint > & a , const vector < mint > & b ) {
if ( a . size () == 0 && b . size () == 0 ) return {};
if ( min < int > ( a . size (), b . size ()) < 128 ) {
vector < mint > ret ( a . size () + b . size () - 1 );
for ( int i = 0 ; i < ( int ) a . size (); ++ i )
for ( int j = 0 ; j < ( int ) b . size (); ++ j ) ret [ i + j ] += a [ i ] * b [ j ];
return ret ;
}
vector < int > s ( a . size ()), t ( b . size ());
for ( int i = 0 ; i < ( int ) a . size (); ++ i ) s [ i ] = a [ i ]. get ();
for ( int i = 0 ; i < ( int ) b . size (); ++ i ) t [ i ] = b [ i ]. get ();
vector < int > u = multiply < int > ( s , t , mint :: get_mod ());
vector < mint > ret ( u . size ());
for ( int i = 0 ; i < ( int ) u . size (); ++ i ) ret [ i ] = mint ( u [ i ]);
return ret ;
}
template < typename T >
vector < u128 > multiply_u128 ( const vector < T > & s , const vector < T > & t ) {
if ( s . size () == 0 && t . size () == 0 ) return {};
if ( min < int > ( s . size (), t . size ()) < 128 ) {
vector < u128 > ret ( s . size () + t . size () - 1 );
for ( int i = 0 ; i < ( int ) s . size (); ++ i )
for ( int j = 0 ; j < ( int ) t . size (); ++ j ) ret [ i + j ] += i64 ( s [ i ]) * t [ j ];
return ret ;
}
auto d0 = mul < T , mint0 > ( s , t );
auto d1 = mul < T , mint1 > ( s , t );
auto d2 = mul < T , mint2 > ( s , t );
int n = d0 . size ();
vector < u128 > ret ( n );
for ( int i = 0 ; i < n ; i ++ ) {
i64 n1 = d1 [ i ]. get (), n2 = d2 [ i ]. get ();
i64 a = d0 [ i ]. get ();
i64 b = ( n1 + m1 - a ) * r01 % m1 ;
i64 c = (( n2 + m2 - a ) * r02r12 + ( m2 - b ) * r12 ) % m2 ;
ret [ i ] = a + b * w1 + u128 ( c ) * w2 ;
}
return ret ;
}
} // namespace ArbitraryNTT
#line 2 "fps/formal-power-series.hpp"
#line 4 "fps/formal-power-series.hpp"
#include <cassert>
#line 8 "fps/formal-power-series.hpp"
using namespace std ;
template < typename mint >
struct FormalPowerSeries : vector < mint > {
using vector < mint >:: vector ;
using FPS = FormalPowerSeries ;
FPS & operator += ( const FPS & r ) {
if ( r . size () > this -> size ()) this -> resize ( r . size ());
for ( int i = 0 ; i < ( int ) r . size (); i ++ ) ( * this )[ i ] += r [ i ];
return * this ;
}
FPS & operator += ( const mint & r ) {
if ( this -> empty ()) this -> resize ( 1 );
( * this )[ 0 ] += r ;
return * this ;
}
FPS & operator -= ( const FPS & r ) {
if ( r . size () > this -> size ()) this -> resize ( r . size ());
for ( int i = 0 ; i < ( int ) r . size (); i ++ ) ( * this )[ i ] -= r [ i ];
return * this ;
}
FPS & operator -= ( const mint & r ) {
if ( this -> empty ()) this -> resize ( 1 );
( * this )[ 0 ] -= r ;
return * this ;
}
FPS & operator *= ( const mint & v ) {
for ( int k = 0 ; k < ( int ) this -> size (); k ++ ) ( * this )[ k ] *= v ;
return * this ;
}
FPS & operator /= ( const FPS & r ) {
if ( this -> size () < r . size ()) {
this -> clear ();
return * this ;
}
int n = this -> size () - r . size () + 1 ;
if (( int ) r . size () <= 64 ) {
FPS f ( * this ), g ( r );
g . shrink ();
mint coeff = g . back (). inverse ();
for ( auto & x : g ) x *= coeff ;
int deg = ( int ) f . size () - ( int ) g . size () + 1 ;
int gs = g . size ();
FPS quo ( deg );
for ( int i = deg - 1 ; i >= 0 ; i -- ) {
quo [ i ] = f [ i + gs - 1 ];
for ( int j = 0 ; j < gs ; j ++ ) f [ i + j ] -= quo [ i ] * g [ j ];
}
* this = quo * coeff ;
this -> resize ( n , mint ( 0 ));
return * this ;
}
return * this = (( * this ). rev (). pre ( n ) * r . rev (). inv ( n )). pre ( n ). rev ();
}
FPS & operator %= ( const FPS & r ) {
* this -= * this / r * r ;
shrink ();
return * this ;
}
FPS operator + ( const FPS & r ) const { return FPS ( * this ) += r ; }
FPS operator + ( const mint & v ) const { return FPS ( * this ) += v ; }
FPS operator - ( const FPS & r ) const { return FPS ( * this ) -= r ; }
FPS operator - ( const mint & v ) const { return FPS ( * this ) -= v ; }
FPS operator * ( const FPS & r ) const { return FPS ( * this ) *= r ; }
FPS operator * ( const mint & v ) const { return FPS ( * this ) *= v ; }
FPS operator / ( const FPS & r ) const { return FPS ( * this ) /= r ; }
FPS operator % ( const FPS & r ) const { return FPS ( * this ) %= r ; }
FPS operator - () const {
FPS ret ( this -> size ());
for ( int i = 0 ; i < ( int ) this -> size (); i ++ ) ret [ i ] = - ( * this )[ i ];
return ret ;
}
void shrink () {
while ( this -> size () && this -> back () == mint ( 0 )) this -> pop_back ();
}
FPS rev () const {
FPS ret ( * this );
reverse ( begin ( ret ), end ( ret ));
return ret ;
}
FPS dot ( FPS r ) const {
FPS ret ( min ( this -> size (), r . size ()));
for ( int i = 0 ; i < ( int ) ret . size (); i ++ ) ret [ i ] = ( * this )[ i ] * r [ i ];
return ret ;
}
// 前 sz 項を取ってくる。sz に足りない項は 0 埋めする
FPS pre ( int sz ) const {
FPS ret ( begin ( * this ), begin ( * this ) + min (( int ) this -> size (), sz ));
if (( int ) ret . size () < sz ) ret . resize ( sz );
return ret ;
}
FPS operator >> ( int sz ) const {
if (( int ) this -> size () <= sz ) return {};
FPS ret ( * this );
ret . erase ( ret . begin (), ret . begin () + sz );
return ret ;
}
FPS operator << ( int sz ) const {
FPS ret ( * this );
ret . insert ( ret . begin (), sz , mint ( 0 ));
return ret ;
}
FPS diff () const {
const int n = ( int ) this -> size ();
FPS ret ( max ( 0 , n - 1 ));
mint one ( 1 ), coeff ( 1 );
for ( int i = 1 ; i < n ; i ++ ) {
ret [ i - 1 ] = ( * this )[ i ] * coeff ;
coeff += one ;
}
return ret ;
}
FPS integral () const {
const int n = ( int ) this -> size ();
FPS ret ( n + 1 );
ret [ 0 ] = mint ( 0 );
if ( n > 0 ) ret [ 1 ] = mint ( 1 );
auto mod = mint :: get_mod ();
for ( int i = 2 ; i <= n ; i ++ ) ret [ i ] = ( - ret [ mod % i ]) * ( mod / i );
for ( int i = 0 ; i < n ; i ++ ) ret [ i + 1 ] *= ( * this )[ i ];
return ret ;
}
mint eval ( mint x ) const {
mint r = 0 , w = 1 ;
for ( auto & v : * this ) r += w * v , w *= x ;
return r ;
}
FPS log ( int deg = - 1 ) const {
assert ( ! ( * this ). empty () && ( * this )[ 0 ] == mint ( 1 ));
if ( deg == - 1 ) deg = ( int ) this -> size ();
return ( this -> diff () * this -> inv ( deg )). pre ( deg - 1 ). integral ();
}
FPS pow ( int64_t k , int deg = - 1 ) const {
const int n = ( int ) this -> size ();
if ( deg == - 1 ) deg = n ;
if ( k == 0 ) {
FPS ret ( deg );
if ( deg ) ret [ 0 ] = 1 ;
return ret ;
}
for ( int i = 0 ; i < n ; i ++ ) {
if (( * this )[ i ] != mint ( 0 )) {
mint rev = mint ( 1 ) / ( * this )[ i ];
FPS ret = ((( * this * rev ) >> i ). log ( deg ) * k ). exp ( deg );
ret *= ( * this )[ i ]. pow ( k );
ret = ( ret << ( i * k )). pre ( deg );
if (( int ) ret . size () < deg ) ret . resize ( deg , mint ( 0 ));
return ret ;
}
if ( __int128_t ( i + 1 ) * k >= deg ) return FPS ( deg , mint ( 0 ));
}
return FPS ( deg , mint ( 0 ));
}
static void * ntt_ptr ;
static void set_fft ();
FPS & operator *= ( const FPS & r );
void ntt ();
void intt ();
void ntt_doubling ();
static int ntt_pr ();
FPS inv ( int deg = - 1 ) const ;
FPS exp ( int deg = - 1 ) const ;
};
template < typename mint >
void * FormalPowerSeries < mint >:: ntt_ptr = nullptr ;
template < int N >
struct FPSBackendPriority : FPSBackendPriority < N - 1 > {};
template < >
struct FPSBackendPriority < 0 > {};
template < typename mint >
void FormalPowerSeries < mint >:: set_fft () {
fps_set_fft_impl (( FormalPowerSeries < mint >* ) nullptr , FPSBackendPriority < 1 > {});
}
template < typename mint >
FormalPowerSeries < mint >& FormalPowerSeries < mint >:: operator *= ( const FPS & r ) {
if ( this -> empty () || r . empty ()) {
this -> clear ();
return * this ;
}
return fps_multiply_impl ( * this , r , FPSBackendPriority < 1 > {});
}
template < typename mint >
void FormalPowerSeries < mint >:: ntt () {
fps_ntt_impl ( * this , FPSBackendPriority < 1 > {});
}
template < typename mint >
void FormalPowerSeries < mint >:: intt () {
fps_intt_impl ( * this , FPSBackendPriority < 1 > {});
}
template < typename mint >
void FormalPowerSeries < mint >:: ntt_doubling () {
fps_ntt_doubling_impl ( * this , FPSBackendPriority < 1 > {});
}
template < typename mint >
int FormalPowerSeries < mint >:: ntt_pr () {
return fps_ntt_pr_impl (( FormalPowerSeries < mint >* ) nullptr ,
FPSBackendPriority < 1 > {});
}
template < typename mint >
FormalPowerSeries < mint > FormalPowerSeries < mint >:: inv ( int deg ) const {
return fps_inv_impl ( * this , deg , FPSBackendPriority < 1 > {});
}
template < typename mint >
FormalPowerSeries < mint > FormalPowerSeries < mint >:: exp ( int deg ) const {
return fps_exp_impl ( * this , deg , FPSBackendPriority < 1 > {});
}
/**
* @brief 多項式/形式的冪級数ライブラリ
*/
#line 7 "fps/arbitrary-fps.hpp"
template < typename mint >
void fps_set_fft_impl ( FormalPowerSeries < mint >* , FPSBackendPriority < 0 > ) {
FormalPowerSeries < mint >:: ntt_ptr = nullptr ;
}
template < typename mint >
void fps_ntt_impl ( FormalPowerSeries < mint >& , FPSBackendPriority < 0 > ) {
exit ( 1 );
}
template < typename mint >
void fps_intt_impl ( FormalPowerSeries < mint >& , FPSBackendPriority < 0 > ) {
exit ( 1 );
}
template < typename mint >
void fps_ntt_doubling_impl ( FormalPowerSeries < mint >& , FPSBackendPriority < 0 > ) {
exit ( 1 );
}
template < typename mint >
int fps_ntt_pr_impl ( FormalPowerSeries < mint >* , FPSBackendPriority < 0 > ) {
exit ( 1 );
}
template < typename mint >
FormalPowerSeries < mint >& fps_multiply_impl ( FormalPowerSeries < mint >& f ,
const FormalPowerSeries < mint >& r ,
FPSBackendPriority < 0 > ) {
auto ret = ArbitraryNTT :: multiply ( f , r );
return f = FormalPowerSeries < mint > ( ret . begin (), ret . end ());
}
template < typename mint >
FormalPowerSeries < mint > fps_inv_impl ( const FormalPowerSeries < mint >& f , int deg ,
FPSBackendPriority < 0 > ) {
assert ( f [ 0 ] != mint ( 0 ));
if ( deg == - 1 ) deg = f . size ();
FormalPowerSeries < mint > ret ({ mint ( 1 ) / f [ 0 ]});
for ( int i = 1 ; i < deg ; i <<= 1 )
ret = ( ret + ret - ret * ret * f . pre ( i << 1 )). pre ( i << 1 );
return ret . pre ( deg );
}
template < typename mint >
FormalPowerSeries < mint > fps_exp_impl ( const FormalPowerSeries < mint >& f , int deg ,
FPSBackendPriority < 0 > ) {
assert ( f . size () == 0 || f [ 0 ] == mint ( 0 ));
if ( deg == - 1 ) deg = ( int ) f . size ();
FormalPowerSeries < mint > ret ({ mint ( 1 )});
for ( int i = 1 ; i < deg ; i <<= 1 ) {
ret = ( ret * ( f . pre ( i << 1 ) + mint ( 1 ) - ret . log ( i << 1 ))). pre ( i << 1 );
}
return ret . pre ( deg );
}