verify/set/LC_exp_of_set_power_series.test.cpp
Depends on
Code
#define PROBLEM "https://judge.yosupo.jp/problem/exp_of_set_power_series"
#include "template/template.hpp"
#include "modint/modint.hpp"
using mint = ModInt < 998244353 > ;
#include "set/exp-of-set-power-series.hpp"
int main () {
int n ;
in ( n );
vector < mint > b ( 1 << n );
in ( b );
auto c = SetPowerSeries :: exp ( b );
out ( c );
}
#line 1 "verify/set/LC_exp_of_set_power_series.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/exp_of_set_power_series"
#line 2 "template/template.hpp"
#include <bits/stdc++.h>
using namespace std ;
#line 2 "template/macro.hpp"
#define rep(i, a, b) for (int i = (a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b) - 1; i >= (a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())
#define YN(b) cout << ((b) ? "YES" : "NO") << "\n";
#define Yn(b) cout << ((b) ? "Yes" : "No") << "\n";
#define yn(b) cout << ((b) ? "yes" : "no") << "\n";
#line 6 "template/template.hpp"
#line 2 "template/util.hpp"
using uint = unsigned int ;
using ll = long long int ;
using ull = unsigned long long ;
using i128 = __int128_t ;
using u128 = __uint128_t ;
template < class T , class S = T >
S SUM ( const vector < T > & a ) {
return accumulate ( ALL ( a ), S ( 0 ));
}
template < class T >
inline bool chmin ( T & a , T b ) {
if ( a > b ) {
a = b ;
return true ;
}
return false ;
}
template < class T >
inline bool chmax ( T & a , T b ) {
if ( a < b ) {
a = b ;
return true ;
}
return false ;
}
template < class T >
int popcnt ( T x ) {
return __builtin_popcountll ( x );
}
template < class T >
int topbit ( T x ) {
return ( x == 0 ? - 1 : 63 - __builtin_clzll ( x ));
}
template < class T >
int lowbit ( T x ) {
return ( x == 0 ? - 1 : __builtin_ctzll ( x ));
}
#line 8 "template/template.hpp"
#line 2 "template/inout.hpp"
struct Fast {
Fast () {
cin . tie ( nullptr );
ios_base :: sync_with_stdio ( false );
cout << fixed << setprecision ( 15 );
}
} fast ;
template < class T1 , class T2 >
istream & operator >> ( istream & is , pair < T1 , T2 > & p ) {
return is >> p . first >> p . second ;
}
template < class T1 , class T2 >
ostream & operator << ( ostream & os , const pair < T1 , T2 > & p ) {
return os << p . first << " " << p . second ;
}
template < class T >
istream & operator >> ( istream & is , vector < T > & a ) {
for ( auto & v : a ) is >> v ;
return is ;
}
template < class T >
ostream & operator << ( ostream & os , const vector < T > & a ) {
for ( auto it = a . begin (); it != a . end ();) {
os << * it ;
if ( ++ it != a . end ()) os << " " ;
}
return os ;
}
template < class T >
ostream & operator << ( ostream & os , const set < T > & st ) {
os << "{" ;
for ( auto it = st . begin (); it != st . end ();) {
os << * it ;
if ( ++ it != st . end ()) os << "," ;
}
os << "}" ;
return os ;
}
template < class T1 , class T2 >
ostream & operator << ( ostream & os , const map < T1 , T2 > & mp ) {
os << "{" ;
for ( auto it = mp . begin (); it != mp . end ();) {
os << it -> first << ":" << it -> second ;
if ( ++ it != mp . end ()) os << "," ;
}
os << "}" ;
return os ;
}
void in () {}
template < typename T , class ... U >
void in ( T & t , U & ... u ) {
cin >> t ;
in ( u ...);
}
void out () { cout << " \n " ; }
template < typename T , class ... U , char sep = ' ' >
void out ( const T & t , const U & ... u ) {
cout << t ;
if ( sizeof ...( u )) cout << sep ;
out ( u ...);
}
#line 10 "template/template.hpp"
#line 2 "template/debug.hpp"
#ifdef LOCAL
#define debug 1
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define debug 0
#define show(...) true
#endif
template < class T >
void _show ( int i , T name ) {
cerr << '\n' ;
}
template < class T1 , class T2 , class ... T3 >
void _show ( int i , const T1 & a , const T2 & b , const T3 & ... c ) {
for (; a [ i ] != ',' && a [ i ] != '\0' ; i ++ ) cerr << a [ i ];
cerr << ":" << b << " " ;
_show ( i + 1 , a , c ...);
}
#line 2 "modint/modint.hpp"
template < unsigned int m = 998244353 >
struct ModInt {
using mint = ModInt ;
unsigned int _v ;
static constexpr unsigned int get_mod () { return m ; }
static mint raw ( int v ) {
mint x ;
x . _v = v ;
return x ;
}
ModInt () : _v ( 0 ) {}
ModInt ( int64_t v ) {
long long x = ( long long )( v % ( long long )( umod ()));
if ( x < 0 ) x += umod ();
_v = ( unsigned int )( x );
}
unsigned int val () const { return _v ; }
mint & operator ++ () {
_v ++ ;
if ( _v == umod ()) _v = 0 ;
return * this ;
}
mint & operator -- () {
if ( _v == 0 ) _v = umod ();
_v -- ;
return * this ;
}
mint operator ++ ( int ) {
mint result = * this ;
++* this ;
return result ;
}
mint operator -- ( int ) {
mint result = * this ;
--* this ;
return result ;
}
mint & operator += ( const mint & rhs ) {
_v += rhs . _v ;
if ( _v >= umod ()) _v -= umod ();
return * this ;
}
mint & operator -= ( const mint & rhs ) {
_v -= rhs . _v ;
if ( _v >= umod ()) _v += umod ();
return * this ;
}
mint & operator *= ( const mint & rhs ) {
unsigned long long z = _v ;
z *= rhs . _v ;
_v = ( unsigned int )( z % umod ());
return * this ;
}
mint & operator /= ( const mint & rhs ) { return * this = * this * rhs . inv (); }
mint operator + () const { return * this ; }
mint operator - () const { return mint () - * this ; }
mint pow ( long long n ) const {
assert ( 0 <= n );
mint x = * this , r = 1 ;
while ( n ) {
if ( n & 1 ) r *= x ;
x *= x ;
n >>= 1 ;
}
return r ;
}
mint inv () const {
assert ( _v );
return pow ( umod () - 2 );
}
friend mint operator + ( const mint & lhs , const mint & rhs ) {
return mint ( lhs ) += rhs ;
}
friend mint operator - ( const mint & lhs , const mint & rhs ) {
return mint ( lhs ) -= rhs ;
}
friend mint operator * ( const mint & lhs , const mint & rhs ) {
return mint ( lhs ) *= rhs ;
}
friend mint operator / ( const mint & lhs , const mint & rhs ) {
return mint ( lhs ) /= rhs ;
}
friend bool operator == ( const mint & lhs , const mint & rhs ) {
return lhs . _v == rhs . _v ;
}
friend bool operator != ( const mint & lhs , const mint & rhs ) {
return lhs . _v != rhs . _v ;
}
friend istream & operator >> ( istream & is , mint & x ) {
return is >> x . _v ;
}
friend ostream & operator << ( ostream & os , const mint & x ) {
return os << x . val ();
}
private:
static constexpr unsigned int umod () { return m ; }
};
#line 5 "verify/set/LC_exp_of_set_power_series.test.cpp"
using mint = ModInt < 998244353 > ;
#line 2 "set/subset-convolution.hpp"
template < class mint , int n_ >
struct SubsetConvolution {
static constexpr int n = n_ ;
using poly = array < mint , n_ + 1 > ;
vector < int > pc ;
SubsetConvolution () {
pc . assign ( 1 << n , 0 );
for ( int i = 1 ; i < pc . size (); i ++ ) pc [ i ] = pc [ i >> 1 ] + ( i & 1 );
}
void poly_add ( poly & p , const poly & q , int d ) {
for ( int i = 0 ; i < d ; i ++ ) p [ i ] += q [ i ];
}
void poly_sub ( poly & p , const poly & q , int d ) {
for ( int i = d ; i <= n ; i ++ ) p [ i ] -= q [ i ];
}
void poly_mul ( poly & p , const poly & q ) {
poly r {};
for ( int i = 0 ; i <= n ; i ++ )
for ( int j = 0 ; j <= n - i ; j ++ )
r [ i + j ] += p [ i ] * q [ j ];
swap ( p , r );
}
vector < poly > lift ( const vector < mint >& a ) {
int n = a . size ();
assert ( n == ( n & - n ));
vector < poly > b ( n );
for ( int i = 0 ; i < n ; i ++ ) {
b [ i ]. fill ( 0 );
b [ i ][ pc [ i ]] = a [ i ];
}
return b ;
}
vector < mint > unlift ( const vector < poly >& b ) {
int n = b . size ();
assert ( n == ( n & - n ));
vector < mint > a ( n );
for ( int i = 0 ; i < n ; i ++ ) a [ i ] = b [ i ][ pc [ i ]];
return a ;
}
void ranked_zeta ( vector < poly >& a ) {
int n = a . size ();
for ( int i = 1 ; i < n ; i <<= 1 )
for ( int j = 0 ; j < n ; j += i * 2 )
for ( int k = 0 ; k < i ; k ++ )
poly_add ( a [ i + j + k ], a [ j + k ], pc [ i + j + k ]);
}
void ranked_mobius ( vector < poly >& a ) {
int n = a . size ();
for ( int i = 1 ; i < n ; i <<= 1 )
for ( int j = 0 ; j < n ; j += i * 2 )
for ( int k = 0 ; k < i ; k ++ )
poly_sub ( a [ i + j + k ], a [ j + k ], pc [ i + j + k ]);
}
void ranked_mul ( vector < poly >& a , const vector < poly >& b ) {
for ( int i = 0 ; i < a . size (); i ++ ) poly_mul ( a [ i ], b [ i ]);
}
vector < mint > multiply ( const vector < mint >& a , const vector < mint >& b ) {
auto p = lift ( a );
auto q = lift ( b );
ranked_zeta ( p );
ranked_zeta ( q );
ranked_mul ( p , q );
ranked_mobius ( p );
return unlift ( p );
}
};
/**
* @brief Subset Convolution
* @docs docs/set/subset-convolution.md
*/
#line 3 "set/exp-of-set-power-series.hpp"
namespace SetPowerSeries {
template < class mint , int sz = 21 >
vector < mint > exp ( const vector < mint >& a ) {
static SubsetConvolution < mint , sz > sc ;
assert ( a [ 0 ] == 0 );
int l = __builtin_ctz ( a . size ());
assert ( a . size () == ( 1 << l ));
vector < mint > f ( 1 << l , 0 );
f [ 0 ] = 1 ;
for ( int k = 0 ; k < l ; k ++ ) {
vector < mint > g ( f . begin (), f . begin () + ( 1 << k ));
vector < mint > h ( a . begin () + ( 1 << k ), a . begin () + ( 2 << k ));
g = sc . multiply ( g , h );
copy ( g . begin (), g . end (), f . begin () + ( 1 << k ));
}
return f ;
}
}; // namespace SetPowerSeries
/**
* @brief Exp Of Set Power Series
*/
#line 7 "verify/set/LC_exp_of_set_power_series.test.cpp"
int main () {
int n ;
in ( n );
vector < mint > b ( 1 << n );
in ( b );
auto c = SetPowerSeries :: exp ( b );
out ( c );
}
Back to top page