特に評価する点が等比数列 $p_i = ar^i$ になっているときに Chirp-Z Transform を用いるとより高速に計算できる。 $t_i = \frac{i(i-1)}{2}$ とおくと $ki = t_{k+i}-t_{k}-t_{i}$ であることより、 $b_i = [x^i] f$ とすると、
$f(ar^i) = \sum_{k=0}^{n-1} b_k(ar^i)^k = \sum_{k=0}^{n-1} b_ka^kr^{ki} = r^{-t_i} \sum_{k=0}^{n-1} b_ka^kr^{-t_k}r^{t_{k+i}}$
より畳み込める。長さ $n, n+m-1$ の列を畳み込んだ $2n+m-2$ 個の値のうち、 $[n-1, n+m-1)$ のみ用いるので $n+m-1$ の巡回畳み込みで良い。
#line 2 "math/poly/MultipointEvaluation.hpp"
#line 2 "other/template.hpp"
#include <bits/stdc++.h>
#line 2 "template/macros.hpp"
#line 4 "template/macros.hpp"
#ifndef __COUNTER__
#define __COUNTER__ __LINE__
#endif
#define OVERLOAD5(a, b, c, d, e, ...) e
#define REP1_0(b, c) REP1_1(b, c)
#define REP1_1(b, c) \
for (ll REP_COUNTER_##c = 0; REP_COUNTER_##c < (ll)(b); ++REP_COUNTER_##c)
#define REP1(b) REP1_0(b, __COUNTER__)
#define REP2(i, b) for (ll i = 0; i < (ll)(b); ++i)
#define REP3(i, a, b) for (ll i = (ll)(a); i < (ll)(b); ++i)
#define REP4(i, a, b, c) for (ll i = (ll)(a); i < (ll)(b); i += (ll)(c))
#define rep(...) OVERLOAD5(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)
#define RREP2(i, a) for (ll i = (ll)(a)-1; i >= 0; --i)
#define RREP3(i, a, b) for (ll i = (ll)(a)-1; i >= (ll)(b); --i)
#define RREP4(i, a, b, c) for (ll i = (ll)(a)-1; i >= (ll)(b); i -= (ll)(c))
#define rrep(...) OVERLOAD5(__VA_ARGS__, RREP4, RREP3, RREP2)(__VA_ARGS__)
#define REPS2(i, b) for (ll i = 1; i <= (ll)(b); ++i)
#define REPS3(i, a, b) for (ll i = (ll)(a) + 1; i <= (ll)(b); ++i)
#define REPS4(i, a, b, c) for (ll i = (ll)(a) + 1; i <= (ll)(b); i += (ll)(c))
#define reps(...) OVERLOAD5(__VA_ARGS__, REPS4, REPS3, REPS2)(__VA_ARGS__)
#define RREPS2(i, a) for (ll i = (ll)(a); i > 0; --i)
#define RREPS3(i, a, b) for (ll i = (ll)(a); i > (ll)(b); --i)
#define RREPS4(i, a, b, c) for (ll i = (ll)(a); i > (ll)(b); i -= (ll)(c))
#define rreps(...) OVERLOAD5(__VA_ARGS__, RREPS4, RREPS3, RREPS2)(__VA_ARGS__)
#define each_for(...) for (auto&& __VA_ARGS__)
#define each_const(...) for (const auto& __VA_ARGS__)
#define all(v) std::begin(v), std::end(v)
#define rall(v) std::rbegin(v), std::rend(v)
#if __cpp_if_constexpr >= 201606L
#define IF_CONSTEXPR constexpr
#else
#define IF_CONSTEXPR
#endif
#define IO_BUFFER_SIZE (1 << 17)
#line 2 "template/alias.hpp"
#line 4 "template/alias.hpp"
using ll = long long ;
using uint = unsigned int ;
using ull = unsigned long long ;
using i128 = __int128_t ;
using u128 = __uint128_t ;
using ld = long double ;
using PLL = std :: pair < ll , ll > ;
template < class T >
using prique = std :: priority_queue < T , std :: vector < T > , std :: greater < T >> ;
template < class T > struct infinity {
static constexpr T value = std :: numeric_limits < T >:: max () / 2 ;
static constexpr T mvalue = std :: numeric_limits < T >:: lowest () / 2 ;
static constexpr T max = std :: numeric_limits < T >:: max ();
static constexpr T min = std :: numeric_limits < T >:: lowest ();
};
#if __cplusplus <= 201402L
template < class T > constexpr T infinity < T >:: value ;
template < class T > constexpr T infinity < T >:: mvalue ;
template < class T > constexpr T infinity < T >:: max ;
template < class T > constexpr T infinity < T >:: min ;
#endif
#if __cpp_variable_templates >= 201304L
template < class T > constexpr T INF = infinity < T >:: value ;
#endif
constexpr ll inf = infinity < ll >:: value ;
constexpr ld EPS = 1e-8 ;
constexpr ld PI = 3.1415926535897932384626 ;
#line 2 "template/type_traits.hpp"
#line 5 "template/type_traits.hpp"
template < class T , class ... Args > struct function_traits_impl {
using result_type = T ;
template < std :: size_t idx >
using argument_type =
typename std :: tuple_element < idx , std :: tuple < Args ... >>:: type ;
using argument_tuple = std :: tuple < Args ... > ;
static constexpr std :: size_t arg_size () { return sizeof ...( Args ); }
};
template < class > struct function_traits_helper ;
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) > {
using type = function_traits_impl < Res , Args ... > ;
};
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) &> {
using type = function_traits_impl < Res , Args ... > ;
};
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) const > {
using type = function_traits_impl < Res , Args ... > ;
};
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) const &> {
using type = function_traits_impl < Res , Args ... > ;
};
#if __cpp_noexcept_function_type >= 201510L
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) noexcept > {
using type = function_traits_impl < Res , Args ... > ;
};
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) & noexcept > {
using type = function_traits_impl < Res , Args ... > ;
};
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) const noexcept > {
using type = function_traits_impl < Res , Args ... > ;
};
template < class Res , class Tp , class ... Args >
struct function_traits_helper < Res ( Tp ::* )( Args ...) const & noexcept > {
using type = function_traits_impl < Res , Args ... > ;
};
#endif
template < class F >
using function_traits = typename function_traits_helper <
decltype ( & std :: remove_reference < F >:: type :: operator ()) >:: type ;
template < class F >
using function_result_type = typename function_traits < F >:: result_type ;
template < class F , std :: size_t idx >
using function_argument_type =
typename function_traits < F >:: template argument_type < idx >;
template < class F >
using function_argument_tuple = typename function_traits < F >:: argument_tuple ;
template < class T >
using is_signed_int =
std :: integral_constant < bool , ( std :: is_integral < T >:: value &&
std :: is_signed < T >:: value ) ||
std :: is_same < T , i128 >:: value > ;
template < class T >
using is_unsigned_int =
std :: integral_constant < bool , ( std :: is_integral < T >:: value &&
std :: is_unsigned < T >:: value ) ||
std :: is_same < T , u128 >:: value > ;
template < class T >
using is_int = std :: integral_constant < bool , is_signed_int < T >:: value ||
is_unsigned_int < T >:: value > ;
template < class T >
using make_signed_int = typename std :: conditional <
std :: is_same < T , i128 >:: value || std :: is_same < T , u128 >:: value ,
std :: common_type < i128 > , std :: make_signed < T >>:: type ;
template < class T >
using make_unsigned_int = typename std :: conditional <
std :: is_same < T , i128 >:: value || std :: is_same < T , u128 >:: value ,
std :: common_type < u128 > , std :: make_unsigned < T >>:: type ;
template < class T , class = void > struct is_range : std :: false_type {};
template < class T >
struct is_range <
T ,
decltype ( all ( std :: declval < typename std :: add_lvalue_reference < T >:: type > ()),
( void ) 0 ) > : std :: true_type {};
template < class T , bool = is_range < T > :: value >
struct range_rank : std :: integral_constant < std :: size_t , 0 > {};
template < class T >
struct range_rank < T , true >
: std :: integral_constant < std :: size_t ,
range_rank < typename T :: value_type >:: value + 1 > {};
template < std :: size_t size > struct int_least {
static_assert ( size <= 128 , "size must be less than or equal to 128" );
using type = typename std :: conditional <
size <= 8 , std :: int_least8_t ,
typename std :: conditional <
size <= 16 , std :: int_least16_t ,
typename std :: conditional <
size <= 32 , std :: int_least32_t ,
typename std :: conditional < size <= 64 , std :: int_least64_t ,
i128 >:: type >:: type >:: type >:: type ;
};
template < std :: size_t size > using int_least_t = typename int_least < size >:: type ;
template < std :: size_t size > struct uint_least {
static_assert ( size <= 128 , "size must be less than or equal to 128" );
using type = typename std :: conditional <
size <= 8 , std :: uint_least8_t ,
typename std :: conditional <
size <= 16 , std :: uint_least16_t ,
typename std :: conditional <
size <= 32 , std :: uint_least32_t ,
typename std :: conditional < size <= 64 , std :: uint_least64_t ,
u128 >:: type >:: type >:: type >:: type ;
};
template < std :: size_t size > using uint_least_t = typename uint_least < size >:: type ;
template < class T >
using double_size_int = int_least < std :: numeric_limits < T >:: digits * 2 + 1 > ;
template < class T > using double_size_int_t = typename double_size_int < T >:: type ;
template < class T >
using double_size_uint = uint_least < std :: numeric_limits < T >:: digits * 2 > ;
template < class T > using double_size_uint_t = typename double_size_uint < T >:: type ;
template < class T >
using double_size =
typename std :: conditional < is_signed_int < T >:: value , double_size_int < T > ,
double_size_uint < T >>:: type ;
template < class T > using double_size_t = typename double_size < T >:: type ;
#line 2 "template/in.hpp"
#line 4 "template/in.hpp"
#include <unistd.h>
#line 8 "template/in.hpp"
template < std :: size_t buf_size = IO_BUFFER_SIZE ,
std :: size_t decimal_precision = 16 >
class Scanner {
private:
template < class , class = void > struct has_scan : std :: false_type {};
template < class T >
struct has_scan <
T , decltype ( std :: declval < T > (). scan ( std :: declval < Scanner &> ()), ( void ) 0 ) >
: std :: true_type {};
int fd ;
int idx , sz ;
bool state ;
std :: array < char , IO_BUFFER_SIZE + 1 > buffer ;
inline char cur () {
if ( idx == sz ) load ();
if ( idx == sz ) {
state = false ;
return '\0' ;
}
return buffer [ idx ];
}
inline void next () {
if ( idx == sz ) load ();
if ( idx == sz ) return ;
++ idx ;
}
public:
inline void load () {
int len = sz - idx ;
if ( idx < len ) return ;
std :: memcpy ( buffer . begin (), buffer . begin () + idx , len );
sz = len + read ( fd , buffer . data () + len , buf_size - len );
buffer [ sz ] = 0 ;
idx = 0 ;
}
Scanner ( int fd ) : fd ( fd ), idx ( 0 ), sz ( 0 ), state ( true ) {}
Scanner ( FILE * fp ) : fd ( fileno ( fp )), idx ( 0 ), sz ( 0 ), state ( true ) {}
inline char scan_char () {
if ( idx == sz ) load ();
return idx == sz ? '\0' : buffer [ idx ++ ];
}
Scanner ignore ( int n = 1 ) {
if ( idx + n > sz ) load ();
idx += n ;
return * this ;
}
inline void discard_space () {
if ( idx == sz ) load ();
while (( '\t' <= buffer [ idx ] && buffer [ idx ] <= '\r' ) ||
buffer [ idx ] == ' ' ) {
if ( ++ idx == sz ) load ();
}
}
void scan ( char & a ) {
discard_space ();
a = scan_char ();
}
void scan ( bool & a ) {
discard_space ();
a = scan_char () != '0' ;
}
void scan ( std :: string & a ) {
discard_space ();
a . clear ();
while ( cur () != '\0' && ( buffer [ idx ] < '\t' || '\r' < buffer [ idx ]) &&
buffer [ idx ] != ' ' ) {
a += scan_char ();
}
}
template < std :: size_t len > void scan ( std :: bitset < len >& a ) {
discard_space ();
if ( idx + len > sz ) load ();
rrep ( i , len ) a [ i ] = buffer [ idx ++ ] != '0' ;
}
template < class T ,
typename std :: enable_if < is_signed_int < T > :: value &&
! has_scan < T >:: value >:: type * = nullptr >
void scan ( T & a ) {
discard_space ();
if ( buffer [ idx ] == '-' ) {
++ idx ;
if ( idx + 40 > sz &&
( idx == sz || ( '0' <= buffer [ sz - 1 ] && buffer [ sz - 1 ] <= '9' )))
load ();
a = 0 ;
while ( '0' <= buffer [ idx ] && buffer [ idx ] <= '9' ) {
a = a * 10 - ( buffer [ idx ++ ] - '0' );
}
}
else {
if ( idx + 40 > sz && '0' <= buffer [ sz - 1 ] && buffer [ sz - 1 ] <= '9' )
load ();
a = 0 ;
while ( '0' <= buffer [ idx ] && buffer [ idx ] <= '9' ) {
a = a * 10 + ( buffer [ idx ++ ] - '0' );
}
}
}
template < class T ,
typename std :: enable_if < is_unsigned_int < T > :: value &&
! has_scan < T >:: value >:: type * = nullptr >
void scan ( T & a ) {
discard_space ();
if ( idx + 40 > sz && '0' <= buffer [ sz - 1 ] && buffer [ sz - 1 ] <= '9' )
load ();
a = 0 ;
while ( '0' <= buffer [ idx ] && buffer [ idx ] <= '9' ) {
a = a * 10 + ( buffer [ idx ++ ] - '0' );
}
}
template < class T ,
typename std :: enable_if < std :: is_floating_point < T > :: value &&
! has_scan < T >:: value >:: type * = nullptr >
void scan ( T & a ) {
discard_space ();
bool sgn = false ;
if ( cur () == '-' ) {
sgn = true ;
next ();
}
a = 0 ;
while ( '0' <= cur () && cur () <= '9' ) {
a = a * 10 + cur () - '0' ;
next ();
}
if ( cur () == '.' ) {
next ();
T n = 0 , d = 1 ;
for ( int i = 0 ;
'0' <= cur () && cur () <= '9' && i < ( int ) decimal_precision ;
++ i ) {
n = n * 10 + cur () - '0' ;
d *= 10 ;
next ();
}
while ( '0' <= cur () && cur () <= '9' ) next ();
a += n / d ;
}
if ( sgn ) a = - a ;
}
private:
template < std :: size_t i , class ... Args > void scan ( std :: tuple < Args ... >& a ) {
if IF_CONSTEXPR ( i < sizeof ...( Args )) {
scan ( std :: get < i > ( a ));
scan < i + 1 , Args ... > ( a );
}
}
public:
template < class ... Args > void scan ( std :: tuple < Args ... >& a ) {
scan < 0 , Args ... > ( a );
}
template < class T , class U > void scan ( std :: pair < T , U >& a ) {
scan ( a . first );
scan ( a . second );
}
template < class T ,
typename std :: enable_if < is_range < T > :: value &&
! has_scan < T >:: value >:: type * = nullptr >
void scan ( T & a ) {
for ( auto && i : a ) scan ( i );
}
template < class T ,
typename std :: enable_if < has_scan < T > :: value >:: type * = nullptr >
void scan ( T & a ) {
a . scan ( * this );
}
void operator ()() {}
template < class Head , class ... Args >
void operator ()( Head & head , Args & ... args ) {
scan ( head );
operator ()( args ...);
}
template < class T > Scanner & operator >> ( T & a ) {
scan ( a );
return * this ;
}
explicit operator bool () const { return state ; }
friend Scanner & getline ( Scanner & scan , std :: string & a ) {
a . erase ();
char c ;
if (( c = scan . scan_char ()) == '\n' || c == '\0' ) return scan ;
a += c ;
while (( c = scan . scan_char ()) != '\n' && c != '\0' ) a += c ;
scan . state = true ;
return scan ;
}
};
Scanner <> scan ( 0 );
#line 2 "template/out.hpp"
#line 8 "template/out.hpp"
struct NumberToString {
char buf [ 10000 ][ 4 ];
constexpr NumberToString () : buf {} {
rep ( i , 10000 ) {
int n = i ;
rrep ( j , 4 ) {
buf [ i ][ j ] = ( char )( '0' + n % 10 );
n /= 10 ;
}
}
}
} constexpr precalc_number_to_string ;
template < std :: size_t buf_size = IO_BUFFER_SIZE , bool debug = false >
class Printer {
private:
template < class , bool = debug , class = void >
struct has_print : std :: false_type {};
template < class T >
struct has_print < T , false ,
decltype ( std :: declval < T > (). print ( std :: declval < Printer &> ()),
( void ) 0 ) > : std :: true_type {};
template < class T >
struct has_print < T , true ,
decltype ( std :: declval < T > (). debug ( std :: declval < Printer &> ()),
( void ) 0 ) > : std :: true_type {};
int fd ;
std :: size_t idx ;
std :: array < char , buf_size > buffer ;
std :: size_t decimal_precision ;
public:
inline void print_char ( char c ) {
#if SHIO_LOCAL
buffer [ idx ++ ] = c ;
if ( idx == buf_size ) flush ();
#else
if IF_CONSTEXPR ( ! debug ) {
buffer [ idx ++ ] = c ;
if ( idx == buf_size ) flush ();
}
#endif
}
inline void flush () {
idx = write ( fd , buffer . begin (), idx );
idx = 0 ;
}
Printer ( int fd ) : fd ( fd ), idx ( 0 ), decimal_precision ( 16 ) {}
Printer ( FILE * fp ) : fd ( fileno ( fp )), idx ( 0 ), decimal_precision ( 16 ) {}
~ Printer () { flush (); }
void set_decimal_precision ( std :: size_t decimal_precision ) {
this -> decimal_precision = decimal_precision ;
}
void print ( char c ) {
if IF_CONSTEXPR ( debug ) print_char ( '\'' );
print_char ( c );
if IF_CONSTEXPR ( debug ) print_char ( '\'' );
}
void print ( bool b ) { print_char (( char )( b + '0' )); }
void print ( const char * a ) {
if IF_CONSTEXPR ( debug ) print_char ( '"' );
for (; * a != '\0' ; ++ a ) print_char ( * a );
if IF_CONSTEXPR ( debug ) print_char ( '"' );
}
template < std :: size_t len > void print ( const char ( & a )[ len ]) {
if IF_CONSTEXPR ( debug ) print_char ( '"' );
for ( auto i : a ) print_char ( i );
if IF_CONSTEXPR ( debug ) print_char ( '"' );
}
void print ( const std :: string & a ) {
if IF_CONSTEXPR ( debug ) print_char ( '"' );
for ( auto i : a ) print_char ( i );
if IF_CONSTEXPR ( debug ) print_char ( '"' );
}
template < std :: size_t len > void print ( const std :: bitset < len >& a ) {
rrep ( i , len ) print_char (( char )( a [ i ] + '0' ));
}
template < class T ,
typename std :: enable_if < is_int < T > :: value &&
! has_print < T >:: value >:: type * = nullptr >
void print ( T a ) {
if ( ! a ) {
print_char ( '0' );
return ;
}
if IF_CONSTEXPR ( is_signed_int < T >:: value ) {
if ( a < 0 ) {
print_char ( '-' );
using U = typename make_unsigned_int < T >:: type ;
print ( static_cast < U > ( - static_cast < U > ( a )));
return ;
}
}
if ( idx + 40 >= buf_size ) flush ();
static char s [ 40 ];
int t = 40 ;
while ( a >= 10000 ) {
int i = a % 10000 ;
a /= 10000 ;
t -= 4 ;
std :: memcpy ( s + t , precalc_number_to_string . buf [ i ], 4 );
}
if ( a >= 1000 ) {
std :: memcpy ( buffer . begin () + idx , precalc_number_to_string . buf [ a ],
4 );
idx += 4 ;
}
else if ( a >= 100 ) {
std :: memcpy ( buffer . begin () + idx ,
precalc_number_to_string . buf [ a ] + 1 , 3 );
idx += 3 ;
}
else if ( a >= 10 ) {
std :: memcpy ( buffer . begin () + idx ,
precalc_number_to_string . buf [ a ] + 2 , 2 );
idx += 2 ;
}
else {
buffer [ idx ++ ] = '0' | a ;
}
std :: memcpy ( buffer . begin () + idx , s + t , 40 - t );
idx += 40 - t ;
}
template < class T ,
typename std :: enable_if < std :: is_floating_point < T > :: value &&
! has_print < T >:: value >:: type * = nullptr >
void print ( T a ) {
if ( a == std :: numeric_limits < T >:: infinity ()) {
print ( "inf" );
return ;
}
if ( a == - std :: numeric_limits < T >:: infinity ()) {
print ( "-inf" );
return ;
}
if ( std :: isnan ( a )) {
print ( "nan" );
return ;
}
if ( a < 0 ) {
print_char ( '-' );
a = - a ;
}
T b = a ;
if ( b < 1 ) {
print_char ( '0' );
}
else {
std :: string s ;
while ( b >= 1 ) {
s += ( char )( '0' + ( int ) std :: fmod ( b , 10.0 ));
b /= 10 ;
}
for ( auto i = s . rbegin (); i != s . rend (); ++ i ) print_char ( * i );
}
print_char ( '.' );
rep ( decimal_precision ) {
a *= 10 ;
print_char (( char )( '0' + ( int ) std :: fmod ( a , 10.0 )));
}
}
private:
template < std :: size_t i , class ... Args >
void print ( const std :: tuple < Args ... >& a ) {
if IF_CONSTEXPR ( i < sizeof ...( Args )) {
if IF_CONSTEXPR ( debug ) print_char ( ',' );
print_char ( ' ' );
print ( std :: get < i > ( a ));
print < i + 1 , Args ... > ( a );
}
}
public:
template < class ... Args > void print ( const std :: tuple < Args ... >& a ) {
if IF_CONSTEXPR ( debug ) print_char ( '(' );
if IF_CONSTEXPR ( sizeof ...( Args ) != 0 ) print ( std :: get < 0 > ( a ));
print < 1 , Args ... > ( a );
if IF_CONSTEXPR ( debug ) print_char ( ')' );
}
template < class T , class U > void print ( const std :: pair < T , U >& a ) {
if IF_CONSTEXPR ( debug ) print_char ( '(' );
print ( a . first );
if IF_CONSTEXPR ( debug ) print_char ( ',' );
print_char ( ' ' );
print ( a . second );
if IF_CONSTEXPR ( debug ) print_char ( ')' );
}
template < class T ,
typename std :: enable_if < is_range < T > :: value &&
! has_print < T >:: value >:: type * = nullptr >
void print ( const T & a ) {
if IF_CONSTEXPR ( debug ) print_char ( '{' );
for ( auto i = std :: begin ( a ); i != std :: end ( a ); ++ i ) {
if ( i != std :: begin ( a )) {
if IF_CONSTEXPR ( debug ) print_char ( ',' );
print_char ( ' ' );
}
print ( * i );
}
if IF_CONSTEXPR ( debug ) print_char ( '}' );
}
template < class T , typename std :: enable_if < has_print < T > :: value &&
! debug >:: type * = nullptr >
void print ( const T & a ) {
a . print ( * this );
}
template < class T , typename std :: enable_if < has_print < T > :: value &&
debug >:: type * = nullptr >
void print ( const T & a ) {
a . debug ( * this );
}
void operator ()() {}
template < class Head , class ... Args >
void operator ()( const Head & head , const Args & ... args ) {
print ( head );
operator ()( args ...);
}
template < class T > Printer & operator << ( const T & a ) {
print ( a );
return * this ;
}
Printer & operator << ( Printer & ( * pf )( Printer & )) { return pf ( * this ); }
};
template < std :: size_t buf_size , bool debug >
Printer < buf_size , debug >& endl ( Printer < buf_size , debug >& pr ) {
pr . print_char ( '\n' );
pr . flush ();
return pr ;
}
template < std :: size_t buf_size , bool debug >
Printer < buf_size , debug >& flush ( Printer < buf_size , debug >& pr ) {
pr . flush ();
return pr ;
}
struct SetPrec {
int n ;
template < class Pr > void print ( Pr & pr ) const { pr . set_decimal_precision ( n ); }
template < class Pr > void debug ( Pr & pr ) const { pr . set_decimal_precision ( n ); }
};
SetPrec setprec ( int n ) { return SetPrec { n }; };
Printer <> print ( 1 ), eprint ( 2 );
void prints () { print . print_char ( '\n' ); }
template < class T > auto prints ( const T & v ) -> decltype ( print << v , ( void ) 0 ) {
print << v ;
print . print_char ( '\n' );
}
template < class Head , class ... Tail >
auto prints ( const Head & head , const Tail & ... tail )
-> decltype ( print << head , ( void ) 0 ) {
print << head ;
print . print_char ( ' ' );
prints ( tail ...);
}
Printer < IO_BUFFER_SIZE , true > debug ( 1 ), edebug ( 2 );
void debugs () { debug . print_char ( '\n' ); }
template < class T > auto debugs ( const T & v ) -> decltype ( debug << v , ( void ) 0 ) {
debug << v ;
debug . print_char ( '\n' );
}
template < class Head , class ... Tail >
auto debugs ( const Head & head , const Tail & ... tail )
-> decltype ( debug << head , ( void ) 0 ) {
debug << head ;
debug . print_char ( ' ' );
debugs ( tail ...);
}
#line 2 "template/bitop.hpp"
#line 6 "template/bitop.hpp"
namespace bitop {
#define KTH_BIT(b, k) (((b) >> (k)) & 1)
#define POW2(k) (1ull << (k))
inline ull next_combination ( int n , ull x ) {
if ( n == 0 ) return 1 ;
ull a = x & - x ;
ull b = x + a ;
return ( x & ~ b ) / a >> 1 | b ;
}
#define rep_comb(i, n, k) \
for (ull i = (1ull << (k)) - 1; i < (1ull << (n)); \
i = bitop::next_combination((n), i))
inline constexpr int msb ( ull x ) {
int res = x ? 0 : - 1 ;
if ( x & 0xFFFFFFFF00000000 ) x &= 0xFFFFFFFF00000000 , res += 32 ;
if ( x & 0xFFFF0000FFFF0000 ) x &= 0xFFFF0000FFFF0000 , res += 16 ;
if ( x & 0xFF00FF00FF00FF00 ) x &= 0xFF00FF00FF00FF00 , res += 8 ;
if ( x & 0xF0F0F0F0F0F0F0F0 ) x &= 0xF0F0F0F0F0F0F0F0 , res += 4 ;
if ( x & 0xCCCCCCCCCCCCCCCC ) x &= 0xCCCCCCCCCCCCCCCC , res += 2 ;
return res + (( x & 0xAAAAAAAAAAAAAAAA ) ? 1 : 0 );
}
inline constexpr int ceil_log2 ( ull x ) { return x ? msb ( x - 1 ) + 1 : 0 ; }
inline constexpr ull reverse ( ull x ) {
x = (( x & 0xAAAAAAAAAAAAAAAA ) >> 1 ) | (( x & 0x5555555555555555 ) << 1 );
x = (( x & 0xCCCCCCCCCCCCCCCC ) >> 2 ) | (( x & 0x3333333333333333 ) << 2 );
x = (( x & 0xF0F0F0F0F0F0F0F0 ) >> 4 ) | (( x & 0x0F0F0F0F0F0F0F0F ) << 4 );
x = (( x & 0xFF00FF00FF00FF00 ) >> 8 ) | (( x & 0x00FF00FF00FF00FF ) << 8 );
x = (( x & 0xFFFF0000FFFF0000 ) >> 16 ) | (( x & 0x0000FFFF0000FFFF ) << 16 );
return ( x >> 32 ) | ( x << 32 );
}
inline constexpr ull reverse ( ull x , int n ) { return reverse ( x ) >> ( 64 - n ); }
} // namespace bitop
inline constexpr int popcnt ( ull x ) noexcept {
#if __cplusplus >= 202002L
return std :: popcount ( x );
#endif
x = ( x & 0x5555555555555555 ) + (( x >> 1 ) & 0x5555555555555555 );
x = ( x & 0x3333333333333333 ) + (( x >> 2 ) & 0x3333333333333333 );
x = ( x & 0x0f0f0f0f0f0f0f0f ) + (( x >> 4 ) & 0x0f0f0f0f0f0f0f0f );
x = ( x & 0x00ff00ff00ff00ff ) + (( x >> 8 ) & 0x00ff00ff00ff00ff );
x = ( x & 0x0000ffff0000ffff ) + (( x >> 16 ) & 0x0000ffff0000ffff );
return ( x & 0x00000000ffffffff ) + (( x >> 32 ) & 0x00000000ffffffff );
}
#line 2 "template/func.hpp"
#line 6 "template/func.hpp"
template < class T , class U , class Comp = std :: less < > >
inline constexpr bool chmin ( T & a , const U & b ,
Comp cmp = Comp ()) noexcept ( noexcept ( cmp ( b , a ))) {
return cmp ( b , a ) ? a = b , true : false ;
}
template < class T , class U , class Comp = std :: less < > >
inline constexpr bool chmax ( T & a , const U & b ,
Comp cmp = Comp ()) noexcept ( noexcept ( cmp ( a , b ))) {
return cmp ( a , b ) ? a = b , true : false ;
}
inline constexpr ll gcd ( ll a , ll b ) {
if ( a < 0 ) a = - a ;
if ( b < 0 ) b = - b ;
while ( b ) {
const ll c = a ;
a = b ;
b = c % b ;
}
return a ;
}
inline constexpr ll lcm ( ll a , ll b ) { return a / gcd ( a , b ) * b ; }
inline constexpr bool is_prime ( ll N ) {
if ( N <= 1 ) return false ;
for ( ll i = 2 ; i * i <= N ; ++ i ) {
if ( N % i == 0 ) return false ;
}
return true ;
}
inline std :: vector < ll > prime_factor ( ll N ) {
std :: vector < ll > res ;
for ( ll i = 2 ; i * i <= N ; ++ i ) {
while ( N % i == 0 ) {
res . push_back ( i );
N /= i ;
}
}
if ( N != 1 ) res . push_back ( N );
return res ;
}
inline constexpr ll my_pow ( ll a , ll b ) {
ll res = 1 ;
while ( b ) {
if ( b & 1 ) res *= a ;
b >>= 1 ;
a *= a ;
}
return res ;
}
inline constexpr ll mod_pow ( ll a , ll b , ll mod ) {
assert ( mod > 0 );
if ( mod == 1 ) return 0 ;
a %= mod ;
ll res = 1 ;
while ( b ) {
if ( b & 1 ) ( res *= a ) %= mod ;
b >>= 1 ;
( a *= a ) %= mod ;
}
return res ;
}
inline PLL extGCD ( ll a , ll b ) {
const ll n = a , m = b ;
ll x = 1 , y = 0 , u = 0 , v = 1 ;
ll t ;
while ( b ) {
t = a / b ;
std :: swap ( a -= t * b , b );
std :: swap ( x -= t * u , u );
std :: swap ( y -= t * v , v );
}
if ( x < 0 ) {
x += m ;
y -= n ;
}
return { x , y };
}
inline ll mod_inv ( ll a , ll mod ) {
ll b = mod ;
ll x = 1 , u = 0 ;
ll t ;
while ( b ) {
t = a / b ;
std :: swap ( a -= t * b , b );
std :: swap ( x -= t * u , u );
}
if ( x < 0 ) x += mod ;
assert ( a == 1 );
return x ;
}
#line 2 "template/util.hpp"
#line 6 "template/util.hpp"
template < class F > class RecLambda {
private:
F f ;
public:
explicit constexpr RecLambda ( F && f_ ) : f ( std :: forward < F > ( f_ )) {}
template < class ... Args >
constexpr auto operator ()( Args && ... args )
-> decltype ( f ( * this , std :: forward < Args > ( args )...)) {
return f ( * this , std :: forward < Args > ( args )...);
}
};
template < class F > inline constexpr RecLambda < F > rec_lambda ( F && f ) {
return RecLambda < F > ( std :: forward < F > ( f ));
}
template < class Head , class ... Tail > struct multi_dim_vector {
using type = std :: vector < typename multi_dim_vector < Tail ... >:: type > ;
};
template < class T > struct multi_dim_vector < T > { using type = T ; };
template < class T , class Arg >
constexpr std :: vector < T > make_vec ( int n , Arg && arg ) {
return std :: vector < T > ( n , std :: forward < Arg > ( arg ));
}
template < class T , class ... Args >
constexpr typename multi_dim_vector < Args ..., T >:: type make_vec ( int n ,
Args && ... args ) {
return typename multi_dim_vector < Args ..., T >:: type (
n , make_vec < T > ( std :: forward < Args > ( args )...));
}
template < class T , class Comp = std :: less < T > > class compressor {
private:
std :: vector < T > dat ;
Comp cmp ;
bool sorted = false ;
public:
compressor () : compressor ( Comp ()) {}
compressor ( const Comp & cmp ) : cmp ( cmp ) {}
compressor ( const std :: vector < T >& vec , bool f = false ,
const Comp & cmp = Comp ())
: dat ( vec ), cmp ( cmp ) {
if ( f ) build ();
}
compressor ( std :: vector < T >&& vec , bool f = false , const Comp & cmp = Comp ())
: dat ( std :: move ( vec )), cmp ( cmp ) {
if ( f ) build ();
}
compressor ( std :: initializer_list < T > il , bool f = false ,
const Comp & cmp = Comp ())
: dat ( all ( il )), cmp ( cmp ) {
if ( f ) build ();
}
void reserve ( int n ) {
assert ( ! sorted );
dat . reserve ( n );
}
void push_back ( const T & v ) {
assert ( ! sorted );
dat . push_back ( v );
}
void push_back ( T && v ) {
assert ( ! sorted );
dat . push_back ( std :: move ( v ));
}
template < class ... Args > void emplace_back ( Args && ... args ) {
assert ( ! sorted );
dat . emplace_back ( std :: forward < Args > ( args )...);
}
void push ( const std :: vector < T >& vec ) {
assert ( ! sorted );
const int n = dat . size ();
dat . resize ( n + vec . size ());
rep ( i , vec . size ()) dat [ n + i ] = vec [ i ];
}
int build () {
assert ( ! sorted );
sorted = true ;
std :: sort ( all ( dat ), cmp );
dat . erase ( std :: unique ( all ( dat ),
[ & ]( const T & a , const T & b ) -> bool {
return ! cmp ( a , b ) && ! cmp ( b , a );
}),
dat . end ());
return dat . size ();
}
const T & operator []( int k ) const & {
assert ( sorted );
assert ( 0 <= k && k < ( int ) dat . size ());
return dat [ k ];
}
int get ( const T & val ) const {
assert ( sorted );
auto itr = std :: lower_bound ( all ( dat ), val , cmp );
assert ( itr != dat . end () && ! cmp ( val , * itr ));
return itr - dat . begin ();
}
int lower_bound ( const T & val ) const {
assert ( sorted );
auto itr = std :: lower_bound ( all ( dat ), val , cmp );
return itr - dat . begin ();
}
int upper_bound ( const T & val ) const {
assert ( sorted );
auto itr = std :: upper_bound ( all ( dat ), val , cmp );
return itr - dat . begin ();
}
bool contains ( const T & val ) const {
assert ( sorted );
return std :: binary_search ( all ( dat ), val , cmp );
}
std :: vector < int > pressed ( const std :: vector < T >& vec ) const {
assert ( sorted );
std :: vector < int > res ( vec . size ());
rep ( i , vec . size ()) res [ i ] = get ( vec [ i ]);
return res ;
}
void press ( std :: vector < T >& vec ) const {
assert ( sorted );
for ( auto && i : vec ) i = get ( i );
}
int size () const {
assert ( sorted );
return dat . size ();
}
};
#line 2 "math/poly/FormalPowerSeries.hpp"
#line 2 "math/convolution/Convolution.hpp"
#line 2 "math/ModInt.hpp"
#line 4 "math/ModInt.hpp"
template < class T , T mod > class StaticModInt {
static_assert ( std :: is_integral < T >:: value , "T must be integral" );
static_assert ( std :: is_unsigned < T >:: value , "T must be unsigned" );
static_assert ( mod > 0 , "mod must be positive" );
static_assert ( mod <= std :: numeric_limits < T >:: max () / 2 ,
"mod * 2 must be less than or equal to T::max()" );
private:
using large_t = typename double_size_uint < T >:: type ;
using signed_t = typename std :: make_signed < T >:: type ;
T val ;
static constexpr unsigned int inv1000000007 [] = {
0 , 1 , 500000004 , 333333336 , 250000002 , 400000003 ,
166666668 , 142857144 , 125000001 , 111111112 , 700000005 };
static constexpr unsigned int inv998244353 [] = {
0 , 1 , 499122177 , 332748118 , 748683265 , 598946612 ,
166374059 , 855638017 , 873463809 , 443664157 , 299473306 };
static constexpr ll mod_inv ( ll a ) {
ll b = mod ;
ll x = 1 , u = 0 ;
ll t = 0 , tmp = 0 ;
while ( b ) {
t = a / b ;
tmp = ( a - t * b );
a = b ;
b = tmp ;
tmp = ( x - t * u );
x = u ;
u = tmp ;
}
if ( x < 0 ) x += mod ;
return x ;
}
public:
constexpr StaticModInt () : val ( 0 ) {}
template < class U ,
typename std :: enable_if < std :: is_integral < U > :: value &&
std :: is_signed < U >:: value >:: type * = nullptr >
constexpr StaticModInt ( U v ) : val {} {
v %= static_cast < signed_t > ( mod );
if ( v < 0 ) v += static_cast < signed_t > ( mod );
val = static_cast < T > ( v );
}
template < class U , typename std :: enable_if <
std :: is_integral < U > :: value &&
std :: is_unsigned < U >:: value >:: type * = nullptr >
constexpr StaticModInt ( U v ) : val ( v % mod ) {}
constexpr T get () const { return val ; }
static constexpr T get_mod () { return mod ; }
static constexpr StaticModInt raw ( T v ) {
StaticModInt res ;
res . val = v ;
return res ;
}
constexpr StaticModInt inv () const {
if IF_CONSTEXPR ( mod == 1000000007 ) {
if ( val <= 10 ) return inv1000000007 [ val ];
}
else if IF_CONSTEXPR ( mod == 998244353 ) {
if ( val <= 10 ) return inv998244353 [ val ];
}
return mod_inv ( val );
}
constexpr StaticModInt & operator ++ () {
++ val ;
if ( val == mod ) val = 0 ;
return * this ;
}
constexpr StaticModInt operator ++ ( int ) {
StaticModInt res = * this ;
++* this ;
return res ;
}
constexpr StaticModInt & operator -- () {
if ( val == 0 ) val = mod ;
-- val ;
return * this ;
}
constexpr StaticModInt operator -- ( int ) {
StaticModInt res = * this ;
--* this ;
return res ;
}
constexpr StaticModInt & operator += ( const StaticModInt & other ) {
val += other . val ;
if ( val >= mod ) val -= mod ;
return * this ;
}
constexpr StaticModInt & operator -= ( const StaticModInt & other ) {
if ( val < other . val ) val += mod ;
val -= other . val ;
return * this ;
}
constexpr StaticModInt & operator *= ( const StaticModInt & other ) {
large_t a = val ;
a *= other . val ;
a %= mod ;
val = a ;
return * this ;
}
constexpr StaticModInt & operator /= ( const StaticModInt & other ) {
* this *= other . inv ();
return * this ;
}
friend constexpr StaticModInt operator + ( const StaticModInt & lhs ,
const StaticModInt & rhs ) {
return StaticModInt ( lhs ) += rhs ;
}
friend constexpr StaticModInt operator - ( const StaticModInt & lhs ,
const StaticModInt & rhs ) {
return StaticModInt ( lhs ) -= rhs ;
}
friend constexpr StaticModInt operator * ( const StaticModInt & lhs ,
const StaticModInt & rhs ) {
return StaticModInt ( lhs ) *= rhs ;
}
friend constexpr StaticModInt operator / ( const StaticModInt & lhs ,
const StaticModInt & rhs ) {
return StaticModInt ( lhs ) /= rhs ;
}
constexpr StaticModInt operator + () const { return StaticModInt ( * this ); }
constexpr StaticModInt operator - () const { return StaticModInt () - * this ; }
friend constexpr bool operator == ( const StaticModInt & lhs ,
const StaticModInt & rhs ) {
return lhs . val == rhs . val ;
}
friend constexpr bool operator != ( const StaticModInt & lhs ,
const StaticModInt & rhs ) {
return lhs . val != rhs . val ;
}
constexpr StaticModInt pow ( ll a ) const {
StaticModInt v = * this , res = 1 ;
while ( a ) {
if ( a & 1 ) res *= v ;
a >>= 1 ;
v *= v ;
}
return res ;
}
template < class Pr > void print ( Pr & a ) const { a . print ( val ); }
template < class Pr > void debug ( Pr & a ) const { a . print ( val ); }
template < class Sc > void scan ( Sc & a ) {
ll v ;
a . scan ( v );
* this = v ;
}
};
#if __cplusplus < 201703L
template < class T , T mod >
constexpr unsigned int StaticModInt < T , mod >:: inv1000000007 [];
template < class T , T mod >
constexpr unsigned int StaticModInt < T , mod >:: inv998244353 [];
#endif
template < unsigned int p > using static_modint = StaticModInt < unsigned int , p > ;
using modint1000000007 = static_modint < 1000000007 > ;
using modint998244353 = static_modint < 998244353 > ;
template < class T , int id > class DynamicModInt {
static_assert ( std :: is_integral < T >:: value , "T must be integral" );
static_assert ( std :: is_unsigned < T >:: value , "T must be unsigned" );
private:
using large_t = typename double_size_uint < T >:: type ;
using signed_t = typename std :: make_signed < T >:: type ;
T val ;
static T mod ;
public:
constexpr DynamicModInt () : val ( 0 ) {}
template < class U ,
typename std :: enable_if < std :: is_integral < U > :: value &&
std :: is_signed < U >:: value >:: type * = nullptr >
constexpr DynamicModInt ( U v ) : val {} {
v %= static_cast < signed_t > ( mod );
if ( v < 0 ) v += static_cast < signed_t > ( mod );
val = static_cast < T > ( v );
}
template < class U , typename std :: enable_if <
std :: is_integral < U > :: value &&
std :: is_unsigned < U >:: value >:: type * = nullptr >
constexpr DynamicModInt ( U v ) : val ( v % mod ) {}
T get () const { return val ; }
static T get_mod () { return mod ; }
static void set_mod ( T v ) {
assert ( v > 0 );
assert ( v <= std :: numeric_limits < T >:: max () / 2 );
mod = v ;
}
static DynamicModInt raw ( T v ) {
DynamicModInt res ;
res . val = v ;
return res ;
}
DynamicModInt inv () const { return mod_inv ( val , mod ); }
DynamicModInt & operator ++ () {
++ val ;
if ( val == mod ) val = 0 ;
return * this ;
}
DynamicModInt operator ++ ( int ) {
DynamicModInt res = * this ;
++* this ;
return res ;
}
DynamicModInt & operator -- () {
if ( val == 0 ) val = mod ;
-- val ;
return * this ;
}
DynamicModInt operator -- ( int ) {
DynamicModInt res = * this ;
--* this ;
return res ;
}
DynamicModInt & operator += ( const DynamicModInt & other ) {
val += other . val ;
if ( val >= mod ) val -= mod ;
return * this ;
}
DynamicModInt & operator -= ( const DynamicModInt & other ) {
if ( val < other . val ) val += mod ;
val -= other . val ;
return * this ;
}
DynamicModInt & operator *= ( const DynamicModInt & other ) {
large_t a = val ;
a *= other . val ;
a %= mod ;
val = a ;
return * this ;
}
DynamicModInt & operator /= ( const DynamicModInt & other ) {
* this *= other . inv ();
return * this ;
}
friend DynamicModInt operator + ( const DynamicModInt & lhs ,
const DynamicModInt & rhs ) {
return DynamicModInt ( lhs ) += rhs ;
}
friend DynamicModInt operator - ( const DynamicModInt & lhs ,
const DynamicModInt & rhs ) {
return DynamicModInt ( lhs ) -= rhs ;
}
friend DynamicModInt operator * ( const DynamicModInt & lhs ,
const DynamicModInt & rhs ) {
return DynamicModInt ( lhs ) *= rhs ;
}
friend DynamicModInt operator / ( const DynamicModInt & lhs ,
const DynamicModInt & rhs ) {
return DynamicModInt ( lhs ) /= rhs ;
}
DynamicModInt operator + () const { return DynamicModInt ( * this ); }
DynamicModInt operator - () const { return DynamicModInt () - * this ; }
friend bool operator == ( const DynamicModInt & lhs , const DynamicModInt & rhs ) {
return lhs . val == rhs . val ;
}
friend bool operator != ( const DynamicModInt & lhs , const DynamicModInt & rhs ) {
return lhs . val != rhs . val ;
}
DynamicModInt pow ( ll a ) const {
DynamicModInt v = * this , res = 1 ;
while ( a ) {
if ( a & 1 ) res *= v ;
a >>= 1 ;
v *= v ;
}
return res ;
}
template < class Pr > void print ( Pr & a ) const { a . print ( val ); }
template < class Pr > void debug ( Pr & a ) const { a . print ( val ); }
template < class Sc > void scan ( Sc & a ) {
ll v ;
a . scan ( v );
* this = v ;
}
};
template < class T , int id > T DynamicModInt < T , id >:: mod = 998244353 ;
template < int id > using dynamic_modint = DynamicModInt < unsigned int , id > ;
using modint = dynamic_modint <- 1 > ;
/**
* @brief ModInt
* @docs docs/math/ModInt.md
*/
#line 5 "math/convolution/Convolution.hpp"
constexpr ull primitive_root_for_convolution ( ull p ) {
if ( p == 2 ) return 1 ;
if ( p == 998244353 ) return 3 ;
if ( p == 469762049 ) return 3 ;
if ( p == 1811939329 ) return 11 ;
if ( p == 2013265921 ) return 11 ;
rep ( g , 2 , p ) {
if ( mod_pow ( g , ( p - 1 ) >> 1 , p ) != 1 ) return g ;
}
return - 1 ;
}
namespace internal {
template < class T > class NthRoot {
private:
static constexpr unsigned int lg =
bitop :: msb (( T :: get_mod () - 1 ) & ( 1 - T :: get_mod ()));
T root [ lg + 1 ];
T inv_root [ lg + 1 ];
T rate [ lg + 1 ];
T inv_rate [ lg + 1 ];
public:
constexpr NthRoot () : root {}, inv_root {}, rate {}, inv_rate {} {
root [ lg ] = T { primitive_root_for_convolution ( T :: get_mod ())}. pow (
( T :: get_mod () - 1 ) >> lg );
inv_root [ lg ] = root [ lg ]. inv ();
rrep ( i , lg ) {
root [ i ] = root [ i + 1 ] * root [ i + 1 ];
inv_root [ i ] = inv_root [ i + 1 ] * inv_root [ i + 1 ];
}
T r = 1 ;
rep ( i , 2 , lg + 1 ) {
rate [ i - 2 ] = r * root [ i ];
r = r * inv_root [ i ];
}
r = 1 ;
rep ( i , 2 , lg + 1 ) {
inv_rate [ i - 2 ] = r * inv_root [ i ];
r = r * root [ i ];
}
}
static constexpr unsigned int get_lg () { return lg ; }
constexpr T get ( int n ) const { return root [ n ]; }
constexpr T inv ( int n ) const { return inv_root [ n ]; }
constexpr T get_rate ( int n ) const { return rate [ n ]; }
constexpr T get_inv_rate ( int n ) const { return inv_rate [ n ]; }
};
template < class T > void number_theoretic_transform ( std :: vector < T >& a ) {
static constexpr NthRoot < T > nth_root ;
int n = a . size ();
for ( int i = n >> 1 ; i > 0 ; i >>= 1 ) {
T z = T :: raw ( 1 );
rep ( j , 0 , n , i << 1 ) {
rep ( k , i ) {
const T x = a [ j + k ];
const T y = a [ j + i + k ] * z ;
a [ j + k ] = x + y ;
a [ j + i + k ] = x - y ;
}
z *= nth_root . get_rate ( popcnt ( j & ~ ( j + ( i << 1 ))));
}
}
}
template < class T > void inverse_number_theoretic_transform ( std :: vector < T >& a ) {
static constexpr NthRoot < T > nth_root ;
int n = a . size ();
for ( int i = 1 ; i < n ; i <<= 1 ) {
T z = T :: raw ( 1 );
rep ( j , 0 , n , i << 1 ) {
rep ( k , i ) {
const T x = a [ j + k ];
const T y = a [ j + i + k ];
a [ j + k ] = x + y ;
a [ j + i + k ] = ( x - y ) * z ;
}
z *= nth_root . get_inv_rate ( popcnt ( j & ~ ( j + ( i << 1 ))));
}
}
T inv_n = T ( 1 ) / n ;
for ( auto && x : a ) x *= inv_n ;
}
template < class T >
std :: vector < T > convolution_naive ( const std :: vector < T >& a ,
const std :: vector < T >& b ) {
int n = a . size (), m = b . size ();
std :: vector < T > c ( n + m - 1 );
rep ( i , n )
rep ( j , m ) c [ i + j ] += a [ i ] * b [ j ];
return c ;
}
template < class T > std :: vector < T > convolution_pow2 ( std :: vector < T > a ) {
int n = a . size () * 2 - 1 ;
int lg = bitop :: msb ( n - 1 ) + 1 ;
if ( n - ( 1 << ( lg - 1 )) <= 5 ) {
-- lg ;
int m = a . size () - ( 1 << ( lg - 1 ));
std :: vector < T > a1 ( a . begin (), a . begin () + m ), a2 ( a . begin () + m , a . end ());
std :: vector < T > c ( n );
std :: vector < T > c1 = convolution_naive ( a1 , a1 );
std :: vector < T > c2 = convolution_naive ( a1 , a2 );
std :: vector < T > c3 = convolution_pow2 ( a2 );
rep ( i , c1 . size ()) c [ i ] += c1 [ i ];
rep ( i , c2 . size ()) c [ i + m ] += c2 [ i ] * 2 ;
rep ( i , c3 . size ()) c [ i + m * 2 ] += c3 [ i ];
return c ;
}
int m = 1 << lg ;
a . resize ( m );
number_theoretic_transform ( a );
rep ( i , m ) a [ i ] *= a [ i ];
inverse_number_theoretic_transform ( a );
a . resize ( n );
return a ;
}
template < class T >
std :: vector < T > convolution ( std :: vector < T > a , std :: vector < T > b ) {
int n = a . size () + b . size () - 1 ;
int lg = bitop :: ceil_log2 ( n );
int m = 1 << lg ;
if ( n - ( 1 << ( lg - 1 )) <= 5 ) {
-- lg ;
if ( a . size () < b . size ()) std :: swap ( a , b );
int m = n - ( 1 << lg );
std :: vector < T > a1 ( a . begin (), a . begin () + m ), a2 ( a . begin () + m , a . end ());
std :: vector < T > c ( n );
std :: vector < T > c1 = convolution_naive ( a1 , b );
std :: vector < T > c2 = convolution ( a2 , b );
rep ( i , c1 . size ()) c [ i ] += c1 [ i ];
rep ( i , c2 . size ()) c [ i + m ] += c2 [ i ];
return c ;
}
a . resize ( m );
b . resize ( m );
number_theoretic_transform ( a );
number_theoretic_transform ( b );
rep ( i , m ) a [ i ] *= b [ i ];
inverse_number_theoretic_transform ( a );
a . resize ( n );
return a ;
}
} // namespace internal
using internal :: inverse_number_theoretic_transform ;
using internal :: number_theoretic_transform ;
template < unsigned int p >
std :: vector < static_modint < p >>
convolution_for_any_mod ( const std :: vector < static_modint < p >>& a ,
const std :: vector < static_modint < p >>& b );
template < unsigned int p >
std :: vector < static_modint < p >>
convolution ( const std :: vector < static_modint < p >>& a ,
const std :: vector < static_modint < p >>& b ) {
unsigned int n = a . size (), m = b . size ();
if ( n == 0 || m == 0 ) return {};
if ( n <= 60 || m <= 60 ) return internal :: convolution_naive ( a , b );
if ( n + m - 1 <= (( 1 - p ) & ( p - 1 ))) {
if ( n == m && a == b ) return internal :: convolution_pow2 ( a );
return internal :: convolution ( a , b );
}
return convolution_for_any_mod ( a , b );
}
template < unsigned int p >
std :: vector < ll > convolution ( const std :: vector < ll >& a ,
const std :: vector < ll >& b ) {
int n = a . size (), m = b . size ();
std :: vector < static_modint < p >> a2 ( n ), b2 ( m );
rep ( i , n ) a2 [ i ] = a [ i ];
rep ( i , m ) b2 [ i ] = b [ i ];
auto c2 = convolution ( a2 , b2 );
std :: vector < ll > c ( c2 . size ());
rep ( i , c2 . size ()) c [ i ] = c2 [ i ]. get ();
return c ;
}
template < unsigned int p >
std :: vector < static_modint < p >>
convolution_for_any_mod ( const std :: vector < static_modint < p >>& a ,
const std :: vector < static_modint < p >>& b ) {
int n = a . size (), m = b . size ();
assert ( n + m - 1 <= ( 1 << 26 ));
std :: vector < ll > a2 ( n ), b2 ( m );
rep ( i , n ) a2 [ i ] = a [ i ]. get ();
rep ( i , m ) b2 [ i ] = b [ i ]. get ();
static constexpr ll MOD1 = 469762049 ;
static constexpr ll MOD2 = 1811939329 ;
static constexpr ll MOD3 = 2013265921 ;
static constexpr ll INV1_2 = mod_pow ( MOD1 , MOD2 - 2 , MOD2 );
static constexpr ll INV1_3 = mod_pow ( MOD1 , MOD3 - 2 , MOD3 );
static constexpr ll INV2_3 = mod_pow ( MOD2 , MOD3 - 2 , MOD3 );
auto c1 = convolution < MOD1 > ( a2 , b2 );
auto c2 = convolution < MOD2 > ( a2 , b2 );
auto c3 = convolution < MOD3 > ( a2 , b2 );
std :: vector < static_modint < p >> res ( n + m - 1 );
rep ( i , n + m - 1 ) {
ll t1 = c1 [ i ];
ll t2 = ( c2 [ i ] - t1 + MOD2 ) * INV1_2 % MOD2 ;
if ( t2 < 0 ) t2 += MOD2 ;
ll t3 =
(( c3 [ i ] - t1 + MOD3 ) * INV1_3 % MOD3 - t2 + MOD3 ) * INV2_3 % MOD3 ;
if ( t3 < 0 ) t3 += MOD3 ;
res [ i ] = static_modint < p > ( t1 + ( t2 + t3 * MOD2 ) % p * MOD1 );
}
return res ;
}
template < class T > void ntt_doubling_ ( std :: vector < T >& a , std :: vector < T > b ) {
static constexpr internal :: NthRoot < T > nth_root ;
int n = a . size ();
const T z = nth_root . get ( bitop :: msb ( n ) + 1 );
T r = 1 ;
rep ( i , n ) {
b [ i ] *= r ;
r *= z ;
}
number_theoretic_transform ( b );
a . reserve ( 2 * n );
a . insert ( a . end (), all ( b ));
}
template < class T > void ntt_doubling_ ( std :: vector < T >& a ) {
static constexpr internal :: NthRoot < T > nth_root ;
int n = a . size ();
auto b = a ;
inverse_number_theoretic_transform ( b );
const T z = nth_root . get ( bitop :: msb ( n ) + 1 );
T r = 1 ;
rep ( i , n ) {
b [ i ] *= r ;
r *= z ;
}
number_theoretic_transform ( b );
a . reserve ( 2 * n );
a . insert ( a . end (), all ( b ));
}
template < unsigned int p > struct is_ntt_friendly : std :: false_type {};
template < > struct is_ntt_friendly < 998244353 > : std :: true_type {};
/**
* @brief Convolution(畳み込み)
* @docs docs/math/convolution/Convolution.md
*/
#line 2 "math/Combinatorics.hpp"
#line 5 "math/Combinatorics.hpp"
template < class T > class Combinatorics {
private:
static std :: vector < T > factorial ;
static std :: vector < T > factinv ;
public:
static void init ( ll n ) {
const int b = factorial . size ();
if ( n < b ) return ;
factorial . resize ( n + 1 );
rep ( i , b , n + 1 ) factorial [ i ] = factorial [ i - 1 ] * i ;
factinv . resize ( n + 1 );
factinv [ n ] = T ( 1 ) / factorial [ n ];
rreps ( i , n , b ) factinv [ i - 1 ] = factinv [ i ] * i ;
}
static T fact ( ll x ) {
if ( x < 0 ) return 0 ;
init ( x );
return factorial [ x ];
}
static T finv ( ll x ) {
if ( x < 0 ) return 0 ;
init ( x );
return factinv [ x ];
}
static T inv ( ll x ) {
if ( x <= 0 ) return 0 ;
init ( x );
return factorial [ x - 1 ] * factinv [ x ];
}
static T perm ( ll n , ll r ) {
if ( r < 0 || r > n ) return 0 ;
init ( n );
return factorial [ n ] * factinv [ n - r ];
}
static T comb ( ll n , ll r ) {
if ( n < 0 ) return 0 ;
if ( r < 0 || r > n ) return 0 ;
init ( n );
return factorial [ n ] * factinv [ n - r ] * factinv [ r ];
}
static T homo ( ll n , ll r ) { return comb ( n + r - 1 , r ); }
static T small_perm ( ll n , ll r ) {
if ( r < 0 || r > n ) return 0 ;
T res = 1 ;
reps ( i , r ) res *= n - r + i ;
return res ;
}
static T small_comb ( ll n , ll r ) {
if ( r < 0 || r > n ) return 0 ;
chmin ( r , n - r );
init ( r );
T res = factinv [ r ];
reps ( i , r ) res *= n - r + i ;
return res ;
}
static T small_homo ( ll n , ll r ) { return small_comb ( n + r - 1 , r ); }
};
template < class T >
std :: vector < T > Combinatorics < T >:: factorial = std :: vector < T > ( 1 , 1 );
template < class T >
std :: vector < T > Combinatorics < T >:: factinv = std :: vector < T > ( 1 , 1 );
/**
* @brief Combinatorics
* @docs docs/math/Combinatorics.md
*/
#line 2 "math/SqrtMod.hpp"
#line 2 "math/MontgomeryModInt.hpp"
#line 4 "math/MontgomeryModInt.hpp"
template < class T > class MontgomeryReduction {
static_assert ( std :: is_integral < T >:: value , "T must be integral" );
static_assert ( std :: is_unsigned < T >:: value , "T must be unsigned" );
private:
using large_t = typename double_size_uint < T >:: type ;
static constexpr int lg = std :: numeric_limits < T >:: digits ;
T mod ;
T r ;
T r2 ; // r^2 mod m
T calc_minv () {
T t = 0 , res = 0 ;
rep ( i , lg ) {
if ( ~ t & 1 ) {
t += mod ;
res += static_cast < T > ( 1 ) << i ;
}
t >>= 1 ;
}
return res ;
}
T minv ;
public:
MontgomeryReduction ( T v ) { set_mod ( v ); }
static constexpr int get_lg () { return lg ; }
void set_mod ( T v ) {
assert ( v > 0 );
assert ( v & 1 );
assert ( v <= std :: numeric_limits < T >:: max () / 2 );
mod = v ;
r = ( - static_cast < T > ( mod )) % mod ;
r2 = ( - static_cast < large_t > ( mod )) % mod ;
minv = calc_minv ();
}
inline T get_mod () const { return mod ; }
inline T get_r () const { return r ; }
T reduce ( large_t x ) const {
large_t tmp =
( x + static_cast < large_t > ( static_cast < T > ( x ) * minv ) * mod ) >> lg ;
return tmp >= mod ? tmp - mod : tmp ;
}
T transform ( large_t x ) const { return reduce ( x * r2 ); }
};
template < class T , int id > class MontgomeryModInt {
private:
using large_t = typename double_size_uint < T >:: type ;
using signed_t = typename std :: make_signed < T >:: type ;
T val ;
static MontgomeryReduction < T > mont ;
public:
MontgomeryModInt () : val ( 0 ) {}
template < class U , typename std :: enable_if <
std :: is_integral < U > :: value &&
std :: is_unsigned < U >:: value >:: type * = nullptr >
MontgomeryModInt ( U x )
: val ( mont . transform (
x < ( static_cast < large_t > ( mont . get_mod ()) << mont . get_lg ())
? x
: x % mont . get_mod ())) {}
template < class U ,
typename std :: enable_if < std :: is_integral < U > :: value &&
std :: is_signed < U >:: value >:: type * = nullptr >
MontgomeryModInt ( U x )
: MontgomeryModInt ( static_cast < typename std :: make_unsigned < U >:: type > (
x < 0 ? - x : x )) {
if ( x < 0 && val ) val = mont . get_mod () - val ;
}
T get () const { return mont . reduce ( val ); }
static T get_mod () { return mont . get_mod (); }
static void set_mod ( T v ) { mont . set_mod ( v ); }
MontgomeryModInt operator + () const { return * this ; }
MontgomeryModInt operator - () const {
MontgomeryModInt res ;
if ( val ) res . val = mont . get_mod () - val ;
return res ;
}
MontgomeryModInt & operator ++ () {
val += mont . get_r ();
if ( val >= mont . get_mod ()) val -= mont . get_mod ();
return * this ;
}
MontgomeryModInt & operator -- () {
if ( val < mont . get_r ()) val += mont . get_mod ();
val -= mont . get_r ();
return * this ;
}
MontgomeryModInt operator ++ ( int ) {
MontgomeryModInt res = * this ;
++* this ;
return res ;
}
MontgomeryModInt operator -- ( int ) {
MontgomeryModInt res = * this ;
--* this ;
return res ;
}
MontgomeryModInt & operator += ( const MontgomeryModInt & rhs ) {
val += rhs . val ;
if ( val >= mont . get_mod ()) val -= mont . get_mod ();
return * this ;
}
MontgomeryModInt & operator -= ( const MontgomeryModInt & rhs ) {
if ( val < rhs . val ) val += mont . get_mod ();
val -= rhs . val ;
return * this ;
}
MontgomeryModInt & operator *= ( const MontgomeryModInt & rhs ) {
val = mont . reduce ( static_cast < large_t > ( val ) * rhs . val );
return * this ;
}
MontgomeryModInt pow ( ull n ) const {
MontgomeryModInt res = 1 , x = * this ;
while ( n ) {
if ( n & 1 ) res *= x ;
x *= x ;
n >>= 1 ;
}
return res ;
}
MontgomeryModInt inv () const { return pow ( mont . get_mod () - 2 ); }
MontgomeryModInt & operator /= ( const MontgomeryModInt & rhs ) {
return * this *= rhs . inv ();
}
friend MontgomeryModInt operator + ( const MontgomeryModInt & lhs ,
const MontgomeryModInt & rhs ) {
return MontgomeryModInt ( lhs ) += rhs ;
}
friend MontgomeryModInt operator - ( const MontgomeryModInt & lhs ,
const MontgomeryModInt & rhs ) {
return MontgomeryModInt ( lhs ) -= rhs ;
}
friend MontgomeryModInt operator * ( const MontgomeryModInt & lhs ,
const MontgomeryModInt & rhs ) {
return MontgomeryModInt ( lhs ) *= rhs ;
}
friend MontgomeryModInt operator / ( const MontgomeryModInt & lhs ,
const MontgomeryModInt & rhs ) {
return MontgomeryModInt ( lhs ) /= rhs ;
}
friend bool operator == ( const MontgomeryModInt & lhs ,
const MontgomeryModInt & rhs ) {
return lhs . val == rhs . val ;
}
friend bool operator != ( const MontgomeryModInt & lhs ,
const MontgomeryModInt & rhs ) {
return lhs . val != rhs . val ;
}
template < class Pr > void print ( Pr & a ) const { a . print ( mont . reduce ( val )); }
template < class Pr > void debug ( Pr & a ) const { a . print ( mont . reduce ( val )); }
template < class Sc > void scan ( Sc & a ) {
ll v ;
a . scan ( v );
* this = v ;
}
};
template < class T , int id >
MontgomeryReduction < T >
MontgomeryModInt < T , id >:: mont = MontgomeryReduction < T > ( 998244353 );
using mmodint = MontgomeryModInt < unsigned int , - 1 > ;
/**
* @brief MontgomeryModInt(モンゴメリ乗算)
* @docs docs/math/MontgomeryModInt.md
*/
#line 5 "math/SqrtMod.hpp"
template < class T > ll sqrt_mod ( ll a ) {
const ll p = T :: get_mod ();
if ( p == 2 ) return a ;
if ( a == 0 ) return 0 ;
if ( T { a }. pow (( p - 1 ) >> 1 ) != 1 ) return - 1 ;
T b = 2 ;
while ( T { b }. pow (( p - 1 ) >> 1 ) == 1 ) ++ b ;
ll s = 0 , t = p - 1 ;
while (( t & 1 ) == 0 ) t >>= 1 , ++ s ;
T x = T { a }. pow (( t + 1 ) >> 1 );
T w = T { a }. pow ( t );
T v = T { b }. pow ( t );
while ( w != 1 ) {
ll k = 0 ;
T y = w ;
while ( y != 1 ) {
y *= y ;
++ k ;
}
T z = v ;
rep ( s - k - 1 ) z *= z ;
x *= z ;
w *= z * z ;
}
return std :: min < ll > ( x . get (), p - x . get ());
}
ll sqrt_mod ( ll a , ll p ) {
if ( p == 2 ) return a ;
using mint = MontgomeryModInt < unsigned int , 493174342 > ;
mint :: set_mod ( p );
return sqrt_mod < mint > ( a );
}
/**
* @brief SqrtMod(平方剰余)
* @docs docs/math/SqrtMod.md
* @see https://37zigen.com/tonelli-shanks-algorithm/
*/
#line 7 "math/poly/FormalPowerSeries.hpp"
template < class T > class FormalPowerSeries : public std :: vector < T > {
private:
using Base = std :: vector < T > ;
using Comb = Combinatorics < T > ;
public:
using Base :: Base ;
FormalPowerSeries ( const Base & v ) : Base ( v ) {}
FormalPowerSeries ( Base && v ) : Base ( std :: move ( v )) {}
FormalPowerSeries & shrink () {
while ( ! this -> empty () && this -> back () == T { 0 }) this -> pop_back ();
return * this ;
}
T eval ( T x ) const {
T res = 0 ;
rrep ( i , this -> size ()) {
res *= x ;
res += ( * this )[ i ];
}
return res ;
}
FormalPowerSeries prefix ( int deg ) const {
assert ( 0 <= deg );
if ( deg < ( int ) this -> size ()) {
return FormalPowerSeries ( this -> begin (), this -> begin () + deg );
}
FormalPowerSeries res ( * this );
res . resize ( deg );
return res ;
}
FormalPowerSeries operator + () const { return * this ; }
FormalPowerSeries operator - () const {
FormalPowerSeries res ( this -> size ());
rep ( i , this -> size ()) res [ i ] = - ( * this )[ i ];
return res ;
}
FormalPowerSeries & operator <<= ( int n ) {
this -> insert ( this -> begin (), n , T { 0 });
return * this ;
}
FormalPowerSeries & operator >>= ( int n ) {
this -> erase ( this -> begin (),
this -> begin () + std :: min ( n , ( int ) this -> size ()));
return * this ;
}
friend FormalPowerSeries operator << ( const FormalPowerSeries & lhs , int rhs ) {
return FormalPowerSeries ( lhs ) <<= rhs ;
}
friend FormalPowerSeries operator >> ( const FormalPowerSeries & lhs , int rhs ) {
return FormalPowerSeries ( lhs ) >>= rhs ;
}
FormalPowerSeries & operator += ( const FormalPowerSeries & rhs ) {
if ( this -> size () < rhs . size ()) this -> resize ( rhs . size ());
rep ( i , rhs . size ()) ( * this )[ i ] += rhs [ i ];
return * this ;
}
FormalPowerSeries & operator -= ( const FormalPowerSeries & rhs ) {
if ( this -> size () < rhs . size ()) this -> resize ( rhs . size ());
rep ( i , rhs . size ()) ( * this )[ i ] -= rhs [ i ];
return * this ;
}
friend FormalPowerSeries operator + ( const FormalPowerSeries & lhs ,
const FormalPowerSeries & rhs ) {
return FormalPowerSeries ( lhs ) += rhs ;
}
friend FormalPowerSeries operator - ( const FormalPowerSeries & lhs ,
const FormalPowerSeries & rhs ) {
return FormalPowerSeries ( lhs ) -= rhs ;
}
friend FormalPowerSeries operator * ( const FormalPowerSeries & lhs ,
const FormalPowerSeries & rhs ) {
return FormalPowerSeries ( convolution ( lhs , rhs ));
}
FormalPowerSeries & operator *= ( const FormalPowerSeries & rhs ) {
return * this = * this * rhs ;
}
FormalPowerSeries & operator *= ( const T & rhs ) {
rep ( i , this -> size ()) ( * this )[ i ] *= rhs ;
return * this ;
}
friend FormalPowerSeries operator * ( const FormalPowerSeries & lhs ,
const T & rhs ) {
return FormalPowerSeries ( lhs ) *= rhs ;
}
friend FormalPowerSeries operator * ( const T & lhs ,
const FormalPowerSeries & rhs ) {
return FormalPowerSeries ( rhs ) *= lhs ;
}
FormalPowerSeries & operator /= ( const T & rhs ) {
rep ( i , this -> size ()) ( * this )[ i ] /= rhs ;
return * this ;
}
friend FormalPowerSeries operator / ( const FormalPowerSeries & lhs ,
const T & rhs ) {
return FormalPowerSeries ( lhs ) /= rhs ;
}
FormalPowerSeries rev () const {
FormalPowerSeries res ( * this );
std :: reverse ( all ( res ));
return res ;
}
friend FormalPowerSeries div ( FormalPowerSeries lhs , FormalPowerSeries rhs ) {
lhs . shrink ();
rhs . shrink ();
if ( lhs . size () < rhs . size ()) {
return FormalPowerSeries {};
}
int n = lhs . size () - rhs . size () + 1 ;
if ( rhs . size () <= 32 ) {
FormalPowerSeries res ( n );
T iv = rhs . back (). inv ();
rrep ( i , n ) {
T d = lhs [ i + rhs . size () - 1 ] * iv ;
res [ i ] = d ;
rep ( j , rhs . size ()) lhs [ i + j ] -= d * rhs [ j ];
}
return res ;
}
return ( lhs . rev (). prefix ( n ) * rhs . rev (). inv ( n )). prefix ( n ). rev ();
}
friend FormalPowerSeries operator % ( FormalPowerSeries lhs ,
FormalPowerSeries rhs ) {
lhs . shrink ();
rhs . shrink ();
if ( lhs . size () < rhs . size ()) {
return lhs ;
}
int n = lhs . size () - rhs . size () + 1 ;
if ( rhs . size () <= 32 ) {
T iv = rhs . back (). inv ();
rrep ( i , n ) {
T d = lhs [ i + rhs . size () - 1 ] * iv ;
rep ( j , rhs . size ()) lhs [ i + j ] -= d * rhs [ j ];
}
return lhs . shrink ();
}
return ( lhs - div ( lhs , rhs ) * rhs ). shrink ();
}
friend std :: pair < FormalPowerSeries , FormalPowerSeries >
divmod ( FormalPowerSeries lhs , FormalPowerSeries rhs ) {
lhs . shrink ();
rhs . shrink ();
if ( lhs . size () < rhs . size ()) {
return { FormalPowerSeries {}, lhs };
}
int n = lhs . size () - rhs . size () + 1 ;
if ( rhs . size () <= 32 ) {
FormalPowerSeries res ( n );
T iv = rhs . back (). inv ();
rrep ( i , n ) {
T d = lhs [ i + rhs . size () - 1 ] * iv ;
res [ i ] = d ;
rep ( j , rhs . size ()) lhs [ i + j ] -= d * rhs [ j ];
}
return { res , lhs . shrink ()};
}
FormalPowerSeries q = div ( lhs , rhs );
return { q , ( lhs - q * rhs ). shrink ()};
}
FormalPowerSeries & operator %= ( const FormalPowerSeries & rhs ) {
return * this = * this % rhs ;
}
FormalPowerSeries diff () const {
if ( this -> empty ()) return {};
FormalPowerSeries res ( this -> size () - 1 );
rep ( i , res . size ()) res [ i ] = ( * this )[ i + 1 ] * ( i + 1 );
return res ;
}
FormalPowerSeries integral () const {
FormalPowerSeries res ( this -> size () + 1 );
res [ 0 ] = 0 ;
Comb :: init ( this -> size ());
rep ( i , this -> size ()) res [ i + 1 ] = ( * this )[ i ] * Comb :: inv ( i + 1 );
return res ;
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries inv ( int deg = - 1 ) const {
assert ( this -> size () > 0 && ( * this )[ 0 ] != 0 );
if ( deg == - 1 ) deg = this -> size ();
FormalPowerSeries f ( 1 , ( * this )[ 0 ]. inv ());
for ( int m = 1 ; m < deg ; m <<= 1 ) {
FormalPowerSeries t = this -> prefix ( 2 * m );
f . resize ( 2 * m );
FormalPowerSeries dft_f = f ;
number_theoretic_transform ( t );
number_theoretic_transform ( dft_f );
rep ( i , 2 * m ) t [ i ] *= dft_f [ i ];
inverse_number_theoretic_transform ( t );
std :: fill ( t . begin (), t . begin () + m , T { 0 });
number_theoretic_transform ( t );
rep ( i , 2 * m ) dft_f [ i ] *= t [ i ];
inverse_number_theoretic_transform ( dft_f );
rep ( i , m , 2 * m ) f [ i ] = - dft_f [ i ];
}
return f . prefix ( deg );
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && ! is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries inv ( int deg = - 1 ) const {
assert ( this -> size () > 0 && ( * this )[ 0 ] != 0 );
if ( deg == - 1 ) deg = this -> size ();
FormalPowerSeries res ( 1 , ( * this )[ 0 ]. inv ());
for ( int m = 1 ; m < deg ; m <<= 1 ) {
res = res * 2 - ( res * res * this -> prefix ( 2 * m )). prefix ( 2 * m );
}
return res . prefix ( deg );
}
FormalPowerSeries log ( int deg = - 1 ) const {
assert ( this -> size () > 0 && ( * this )[ 0 ] == 1 );
if ( deg == - 1 ) deg = this -> size ();
return ( diff (). prefix ( deg - 1 ) * inv ( deg - 1 )). prefix ( deg - 1 ). integral ();
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries exp ( int deg = - 1 ) const {
assert ( this -> size () > 0 && ( * this )[ 0 ] == 0 );
if ( deg == - 1 ) deg = this -> size ();
FormalPowerSeries df = this -> diff ();
FormalPowerSeries f ( 1 , 1 );
FormalPowerSeries g ( 1 , 1 );
FormalPowerSeries dft_f = f ;
number_theoretic_transform ( dft_f );
for ( int m = 1 ; m < deg ; m <<= 1 ) {
dft_f . ntt_doubling ( f );
f . resize ( 2 * m );
g . resize ( 2 * m );
FormalPowerSeries dft_g = g ;
number_theoretic_transform ( dft_g );
FormalPowerSeries t = df . prefix ( 2 * m );
number_theoretic_transform ( t );
rep ( i , 2 * m ) t [ i ] *= dft_f [ i ];
inverse_number_theoretic_transform ( t );
std :: fill ( t . begin (), t . begin () + m - 1 , T { 0 });
number_theoretic_transform ( t );
rep ( i , 2 * m ) t [ i ] *= dft_g [ i ];
inverse_number_theoretic_transform ( t );
std :: fill ( t . begin (), t . begin () + m - 1 , T { 0 });
t = t . prefix ( 2 * m - 1 ). integral ();
number_theoretic_transform ( t );
rep ( i , 2 * m ) t [ i ] *= dft_f [ i ];
inverse_number_theoretic_transform ( t );
rep ( i , m , 2 * m ) f [ i ] = t [ i ];
if ( 2 * m < deg ) {
dft_f = f ;
number_theoretic_transform ( dft_f );
FormalPowerSeries t = dft_f ;
rep ( i , 2 * m ) t [ i ] *= dft_g [ i ];
inverse_number_theoretic_transform ( t );
std :: fill ( t . begin (), t . begin () + m , T { 0 });
number_theoretic_transform ( t );
rep ( i , 2 * m ) t [ i ] *= dft_g [ i ];
inverse_number_theoretic_transform ( t );
rep ( i , m , 2 * m ) g [ i ] = - t [ i ];
}
}
return f . prefix ( deg );
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && ! is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries exp ( int deg = - 1 ) const {
assert ( this -> size () > 0 && ( * this )[ 0 ] == 0 );
if ( deg == - 1 ) deg = this -> size ();
FormalPowerSeries res ( 1 , 1 );
for ( int m = 1 ; m < deg ; m <<= 1 ) {
res = ( res * ( prefix ( 2 * m ) - res . log ( 2 * m )) + res ). prefix ( 2 * m );
}
return res . prefix ( deg );
}
FormalPowerSeries pow ( ll k , int deg = - 1 ) const {
if ( deg == - 1 ) deg = this -> size ();
if ( deg == 0 ) return {};
if ( k == 0 ) {
FormalPowerSeries res ( deg );
res [ 0 ] = 1 ;
return res ;
}
if ( k == 1 ) return prefix ( deg );
if ( k == 2 ) return ( * this * * this ). prefix ( deg );
T a ;
int d = - 1 ;
rep ( i , this -> size ()) {
if (( * this )[ i ] != 0 ) {
a = ( * this )[ i ];
d = i ;
break ;
}
}
if ( d == - 1 ) {
FormalPowerSeries res ( deg );
return res ;
}
if (( i128 ) d * k >= deg ) {
FormalPowerSeries res ( deg );
return res ;
}
deg -= d * k ;
FormalPowerSeries res = ((( * this >> d ) / a ). log ( deg ) * k ). exp ( deg );
res *= a . pow ( k );
res <<= d * k ;
return res ;
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries sqrt ( int deg = - 1 ) const {
if ( deg == - 1 ) deg = this -> size ();
T a ;
int d = - 1 ;
rep ( i , this -> size ()) {
if (( * this )[ i ] != 0 ) {
a = ( * this )[ i ];
d = i ;
break ;
}
}
if ( d == - 1 ) {
FormalPowerSeries res ( deg );
return res ;
}
if ( d & 1 ) return {};
deg -= ( d >> 1 );
if ( deg <= 0 ) {
FormalPowerSeries res ( deg );
return res ;
}
FormalPowerSeries t = ( * this >> d );
T sq = sqrt_mod < T > ( a . get ());
if ( sq == - 1 ) return {};
FormalPowerSeries f ( 1 , sq ), g ( 1 , 1 / sq ), dft_f = f ;
number_theoretic_transform ( dft_f );
for ( int m = 1 ; m < deg ; m <<= 1 ) {
dft_f . ntt_doubling ( f );
f . resize ( 2 * m );
g . resize ( 2 * m );
FormalPowerSeries dft_g = g ;
number_theoretic_transform ( dft_g );
FormalPowerSeries u = dft_f ;
rep ( i , 2 * m ) u [ i ] *= dft_f [ i ];
FormalPowerSeries tx = t . prefix ( 2 * m );
number_theoretic_transform ( tx );
rep ( i , 2 * m ) u [ i ] = ( tx [ i ] - u [ i ]) * dft_g [ i ];
inverse_number_theoretic_transform ( u );
rep ( i , m , 2 * m ) f [ i ] = u [ i ] / 2 ;
if ( 2 * m < deg ) {
dft_f = f ;
number_theoretic_transform ( dft_f );
FormalPowerSeries u = dft_g ;
rep ( i , 2 * m ) u [ i ] *= dft_f [ i ];
inverse_number_theoretic_transform ( u );
std :: fill ( u . begin (), u . begin () + m , T { 0 });
number_theoretic_transform ( u );
rep ( i , 2 * m ) u [ i ] *= dft_g [ i ];
inverse_number_theoretic_transform ( u );
rep ( i , m , 2 * m ) g [ i ] = - u [ i ];
}
}
return f . prefix ( deg ) << ( d >> 1 );
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && ! is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries sqrt ( int deg = - 1 ) const {
if ( deg == - 1 ) deg = this -> size ();
T a ;
int d = - 1 ;
rep ( i , this -> size ()) {
if (( * this )[ i ] != 0 ) {
a = ( * this )[ i ];
d = i ;
break ;
}
}
if ( d == - 1 ) {
FormalPowerSeries res ( deg );
return res ;
}
if ( d & 1 ) return {};
deg -= ( d >> 1 );
if ( deg <= 0 ) {
FormalPowerSeries res ( deg );
return res ;
}
FormalPowerSeries t = ( * this >> d );
T sq = sqrt_mod < T > ( a . get ());
if ( sq == - 1 ) return {};
FormalPowerSeries f ( 1 , sq );
for ( int m = 1 ; m < deg ; m <<= 1 ) {
f = ( f + t * f . inv ( 2 * m )). prefix ( 2 * m ) / 2 ;
}
return f . prefix ( deg ) << ( d >> 1 );
}
FormalPowerSeries compose ( FormalPowerSeries g , int deg = - 1 ) const {
if ( this -> empty ()) return {};
if ( g . empty ()) return {( * this )[ 0 ]};
assert ( g [ 0 ] == 0 );
int n = deg == - 1 ? this -> size () : deg ;
int m = 1 << ( bitop :: ceil_log2 (
std :: max < int > ( 1 , std :: sqrt ( n / std :: log2 ( n )))) +
1 );
FormalPowerSeries p = g . prefix ( m ), q = g >> m ;
p . shrink ();
q . shrink ();
int l = ( n + m - 1 ) / m ;
std :: vector < FormalPowerSeries > fs ( this -> size ());
rep ( i , this -> size ()) fs [ i ] = FormalPowerSeries {( * this )[ i ]};
FormalPowerSeries pd = p . diff ();
int z = 0 ;
while ( z < ( int ) pd . size () && pd [ z ] == T { 0 }) z ++ ;
if ( z == ( int ) pd . size ()) {
FormalPowerSeries ans ;
rrep ( i , l ) {
ans = (( ans * q ) << m ). prefix ( n - i * m ) +
FormalPowerSeries {( * this )[ i ]};
}
return ans ;
}
pd = ( pd >> z ). inv ( n );
FormalPowerSeries t = p ;
for ( int k = 1 ; fs . size () > 1 ; k <<= 1 ) {
std :: vector < FormalPowerSeries > nfs (( fs . size () + 1 ) / 2 );
t . resize ( 1 << ( bitop :: ceil_log2 ( t . size ()) + 1 ));
number_theoretic_transform ( t );
rep ( i , fs . size () / 2 ) {
nfs [ i ] = std :: move ( fs [ 2 * i ]);
fs [ 2 * i + 1 ]. resize ( t . size ());
number_theoretic_transform ( fs [ 2 * i + 1 ]);
rep ( j , t . size ()) fs [ 2 * i + 1 ][ j ] *= t [ j ];
inverse_number_theoretic_transform ( fs [ 2 * i + 1 ]);
if (( int ) fs [ 2 * i + 1 ]. size () > n ) fs [ 2 * i + 1 ]. resize ( n );
nfs [ i ] += fs [ 2 * i + 1 ];
}
if ( fs . size () & 1 ) nfs . back () = std :: move ( fs . back ());
fs = std :: move ( nfs );
if ( fs . size () > 1 ) {
rep ( i , t . size ()) t [ i ] *= t [ i ];
inverse_number_theoretic_transform ( t );
if (( int ) t . size () > n ) t . resize ( n );
}
}
FormalPowerSeries fp = fs [ 0 ]. prefix ( n );
FormalPowerSeries res = fp ;
int n2 = 1 << ( bitop :: ceil_log2 ( n ) + 1 );
FormalPowerSeries qpow ( n2 );
qpow [ 0 ] = 1 ;
q . resize ( n2 );
number_theoretic_transform ( q );
pd . resize ( n2 );
number_theoretic_transform ( pd );
rep ( i , 1 , l ) {
if (( n - i * m ) * 4 <= n2 ) {
while (( n - i * m ) * 4 <= n2 ) {
n2 /= 2 ;
}
inverse_number_theoretic_transform ( q );
q . resize ( n - i * m );
q . resize ( n2 );
number_theoretic_transform ( q );
inverse_number_theoretic_transform ( pd );
pd . resize ( n - i * m );
pd . resize ( n2 );
number_theoretic_transform ( pd );
}
qpow . resize ( n - i * m );
qpow . resize ( n2 );
number_theoretic_transform ( qpow );
rep ( j , n2 ) qpow [ j ] *= q [ j ];
inverse_number_theoretic_transform ( qpow );
qpow . resize ( n - i * m );
fp = fp . diff () >> z ;
fp . resize ( n - i * m );
fp . resize ( n2 );
number_theoretic_transform ( fp );
rep ( j , n2 ) fp [ j ] *= pd [ j ];
inverse_number_theoretic_transform ( fp );
fp . resize ( n - i * m );
res += (( qpow * fp ). prefix ( n - i * m ) * Comb :: finv ( i )) << ( i * m );
}
return res ;
}
FormalPowerSeries compinv ( int deg = - 1 ) const {
assert ( this -> size () >= 2 && ( * this )[ 0 ] == 0 && ( * this )[ 1 ] != 0 );
if ( deg == - 1 ) deg = this -> size ();
FormalPowerSeries fd = diff ();
FormalPowerSeries x { 0 , 1 };
FormalPowerSeries res { 0 , ( * this )[ 1 ]. inv ()};
for ( int m = 2 ; m < deg ; m <<= 1 ) {
auto tmp = prefix ( 2 * m ). compose ( res );
auto d = tmp . diff ();
auto gd = res . diff ();
res -=
(( tmp - x ) * ( d . inv ( 2 * m ) * gd ). prefix ( 2 * m )). prefix ( 2 * m );
}
return res . prefix ( deg );
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries & ntt_doubling () {
ntt_doubling_ ( * this );
return * this ;
}
template < bool AlwaysTrue = true ,
typename std :: enable_if <
AlwaysTrue && is_ntt_friendly < T :: get_mod ()> :: value >:: type * =
nullptr >
FormalPowerSeries & ntt_doubling ( const std :: vector < T >& b ) {
ntt_doubling_ ( * this , b );
return * this ;
}
};
/**
* @brief FormalPowerSeries(形式的冪級数)
* @docs docs/math/poly/FormalPowerSeries.md
* @see https://nyaannyaan.github.io/library/fps/formal-power-series.hpp
*/
#line 5 "math/poly/MultipointEvaluation.hpp"
namespace internal {
template < class T > class ProductTree {
private:
int n ;
std :: vector < FormalPowerSeries < T >> dat ;
public:
ProductTree ( const std :: vector < T >& xs ) {
n = xs . size ();
dat . resize ( n << 1 );
rep ( i , n ) dat [ i + n ] = FormalPowerSeries < T > { - xs [ i ], 1 };
rrep ( i , n , 1 ) dat [ i ] = dat [ i << 1 ] * dat [ i << 1 | 1 ];
}
const FormalPowerSeries < T >& operator []( int k ) const & { return dat [ k ]; }
FormalPowerSeries < T > operator []( int k ) && { return std :: move ( dat [ k ]); }
};
template < class T >
std :: vector < T > multipoint_evaluation ( const FormalPowerSeries < T >& a ,
const std :: vector < T >& b ,
const ProductTree < T >& c ) {
int m = b . size ();
std :: vector < FormalPowerSeries < T >> d ( m << 1 );
d [ 1 ] = a % c [ 1 ];
rep ( i , 2 , m << 1 ) d [ i ] = d [ i >> 1 ] % c [ i ];
std :: vector < T > e ( m );
rep ( i , m ) e [ i ] = d [ m + i ]. empty () ? T { 0 } : d [ m + i ][ 0 ];
return e ;
}
} // namespace internal
template < class T >
std :: vector < T > multipoint_evaluation ( const FormalPowerSeries < T >& a ,
const std :: vector < T >& b ) {
if ( a . empty () || b . empty ()) return std :: vector < T > ( b . size (), T { 0 });
if ( a . size () <= 32 || b . size () <= 32 ) {
std :: vector < T > res ( b . size ());
rep ( i , b . size ()) res [ i ] = a . eval ( b [ i ]);
return res ;
}
return internal :: multipoint_evaluation ( a , b , internal :: ProductTree < T > ( b ));
}
template < class T >
std :: vector < T > multipoint_evaluation_geometric ( const FormalPowerSeries < T >& f ,
T a , T r , int m ) {
if ( f . empty () || m == 0 ) return std :: vector < T > ( m , T { 0 });
if ( a == 0 || r == 1 ) return std :: vector < T > ( m , f . eval ( a ));
if ( f . size () <= 32 || m <= 32 ) {
std :: vector < T > res ( m );
rep ( i , m ) {
res [ i ] = f . eval ( a );
a *= r ;
}
return res ;
}
if ( r == 0 ) {
std :: vector < T > res ( m , f . eval ( 0 ));
res [ 0 ] = f . eval ( a );
return res ;
}
int n = f . size ();
int l = 1 << bitop :: ceil_log2 ( n + m - 1 );
std :: vector < T > p ( l ), q ( l );
T ir = T { 1 } / r , t = 1 , t2 = 1 ;
rep ( i , n ) {
p [ n - i - 1 ] = f [ i ] * t ;
t *= a * t2 ;
t2 *= ir ;
}
t = t2 = 1 ;
rep ( i , n + m - 1 ) {
q [ i ] = t ;
t *= t2 ;
t2 *= r ;
}
number_theoretic_transform ( p );
number_theoretic_transform ( q );
rep ( i , l ) p [ i ] *= q [ i ];
inverse_number_theoretic_transform ( p );
std :: vector < T > ans ( p . begin () + ( n - 1 ), p . begin () + ( n + m - 1 ));
t = t2 = 1 ;
rep ( i , m ) {
ans [ i ] *= t ;
t *= t2 ;
t2 *= ir ;
}
return ans ;
}
/**
* @brief MultipointEvaluation(多点評価)
* @docs docs/math/poly/MultipointEvaluation.md
*/