传送门
题意:有
(
k
n
)
\binom{k}{n}
( n k ) 种情况,每种情况是选出来的数之积,求
n
∈
[
1
,
m
]
n\in[1,m]
n ∈ [ 1 , m ] 的每种情况的值 那么就是求
∏
(
1
+
i
x
)
\prod(1+ix)
∏ ( 1 + i x ) 的
[
1
,
n
]
[1,n]
[ 1 , n ] 项系数,那么用
ln
,
exp
\ln,\exp
ln , exp 来转换,即
exp
(
∑
ln
(
1
+
i
x
)
)
\exp(\sum \ln(1+ix))
exp ( ∑ ln ( 1 + i x ) ) ,把
ln
\ln
ln 泰勒展开,就是
exp
(
∑
i
∑
j
≥
1
i
j
(
−
1
)
j
+
1
j
x
j
)
=
exp
(
∑
j
≥
1
(
−
1
)
j
+
1
j
x
j
(
∑
i
i
j
)
)
\exp(\sum_i\sum_{j\ge 1}\frac{i^j(-1)^{j+1}}{j}x^j)=\exp(\sum_{j\ge 1}\frac{(-1)^{j+1}}{j}x^j(\sum_i i^j))
exp ( i ∑ j ≥ 1 ∑ j i j ( − 1 ) j + 1 x j ) = exp ( j ≥ 1 ∑ j ( − 1 ) j + 1 x j ( i ∑ i j ) ) 考虑快速对
j
∈
[
1
,
n
]
j\in[1,n]
j ∈ [ 1 , n ] 求
∑
i
i
j
\sum_i i^j
∑ i i j ,这个拉格朗日插值可以
O
(
n
2
)
O(n^2)
O ( n 2 ) 做 写出生成函数
F
(
x
)
=
∑
j
(
∑
i
i
j
)
x
j
j
!
F(x)=\sum_{j}(\sum_{i}i^j)\frac{x^j}{j!}
F ( x ) = ∑ j ( ∑ i i j ) j ! x j ,上回又道题是写成
o
g
f
ogf
o g f ,但是凉了,
e
g
f
egf
e g f 有巧妙的性质:
F
(
x
)
=
∑
i
∑
j
i
j
x
j
j
!
=
∑
i
e
i
x
=
e
(
k
+
1
)
x
−
e
x
e
x
−
1
F(x)=\sum_{i}\sum_j\frac{i^jx^j}{j!}=\sum_ie^{ix}=\frac{e^{(k+1)x}-e^x}{e^x-1}
F ( x ) = i ∑ j ∑ j ! i j x j = i ∑ e i x = e x − 1 e ( k + 1 ) x − e x 同时约一个
x
x
x 即可多项式求逆
#include< bits/ stdc++ . h>
#define cs const
#define pb push_back
#define poly vector< int >
using namespace std;
cs int Mod = 998244353 ;
int add ( int a, int b) { return a + b >= Mod ? a + b - Mod : a + b; }
int dec ( int a, int b) { return a - b < 0 ? a - b + Mod : a - b; }
int mul ( int a, int b) { return 1 ll * a * b % Mod; }
void Add ( int & a, int b) { a = add ( a, b) ; }
void Mul ( int & a, int b) { a = mul ( a, b) ; }
void Dec ( int & a, int b) { a = dec ( a, b) ; }
int ksm ( int a, int b) { int as= 1 ; for ( ; b; b>>= 1 , a= mul ( a, a) ) if ( b& 1 ) as= mul ( as, a) ; return as; }
cs int N = 5e5 + 50 ;
int k, n, fc[ N] , ifc[ N] ;
cs int K = 20 ;
int up, bit; poly rev;
poly w[ K+ 1 ] ; int iv[ 1 << K| 5 ] ;
void OGF ( poly a) { for ( int c: a) cout<< c<< " " ; puts ( "" ) ; }
void EGF ( poly a) { for ( int i= 0 ; i< a. size ( ) ; i++ ) cout<< mul ( a[ i] , fc[ i] ) << " " ; puts ( "" ) ; }
void NTT_init ( ) {
for ( int i= 1 ; i<= K; i++ ) w[ i] . resize ( 1 << ( i- 1 ) ) ;
int wn= ksm ( 3 , ( Mod- 1 ) / ( 1 << K) ) ; w[ K] [ 0 ] = 1 ;
for ( int i= 1 ; i< ( 1 << ( K- 1 ) ) ; i++ ) w[ K] [ i] = mul ( w[ K] [ i- 1 ] , wn) ;
for ( int i= K- 1 ; i; i-- ) for ( int j= 0 ; j< ( 1 << ( i- 1 ) ) ; j++ ) w[ i] [ j] = w[ i+ 1 ] [ j<< 1 ] ;
iv[ 0 ] = iv[ 1 ] = 1 ; for ( int i= 2 ; i<= ( 1 << K) ; i++ ) iv[ i] = mul ( Mod- Mod/ i, iv[ Mod% i] ) ;
}
void Fac_init ( int n) {
fc[ 0 ] = fc[ 1 ] = ifc[ 0 ] = ifc[ 1 ] = 1 ;
for ( int i= 2 ; i<= n; i++ ) fc[ i] = mul ( fc[ i- 1 ] , i) ;
for ( int i= 2 ; i<= n; i++ ) ifc[ i] = mul ( ifc[ i- 1 ] , iv[ i] ) ;
}
void init ( int deg) {
up= 1 ; bit= 0 ; while ( up< deg) up<<= 1 , ++ bit; rev. resize ( up) ;
for ( int i= 0 ; i< up; i++ ) rev[ i] = ( rev[ i>> 1 ] >> 1 ) | ( ( i& 1 ) << ( bit- 1 ) ) ;
}
void NTT ( poly & a, int typ= 1 ) {
for ( int i= 0 ; i< up; i++ ) if ( i< rev[ i] ) swap ( a[ i] , a[ rev[ i] ] ) ;
for ( int i= 1 , l= 1 ; i< up; i<<= 1 , ++ l)
for ( int j= 0 ; j< up; j+= ( i<< 1 ) )
for ( int k= 0 ; k< i; k++ ) {
int x= a[ k+ j] , y= mul ( w[ l] [ k] , a[ k+ j+ i] ) ;
a[ k+ j] = add ( x, y) ; a[ k+ j+ i] = dec ( x, y) ;
}
if ( typ== - 1 ) {
reverse ( a. begin ( ) + 1 , a. end ( ) ) ;
for ( int i= 0 ; i< up; i++ ) Mul ( a[ i] , iv[ up] ) ;
}
}
poly operator * ( poly a, poly b) {
int deg= a. size ( ) + b. size ( ) - 1 ;
if ( a. size ( ) <= 16 || b. size ( ) <= 16 ) {
poly c ( deg, 0 ) ;
for ( int i= 0 ; i< ( int ) a. size ( ) ; i++ )
for ( int j= 0 ; j< ( int ) b. size ( ) ; j++ )
Add ( c[ i+ j] , mul ( a[ i] , b[ j] ) ) ; return c;
}
init ( deg) ; a. resize ( up) ; b. resize ( up) ; NTT ( a) ; NTT ( b) ;
for ( int i= 0 ; i< up; i++ ) Mul ( a[ i] , b[ i] ) ; NTT ( a, - 1 ) ;
a. resize ( deg) ; return a;
}
poly inv ( poly a, int deg) {
poly b ( 1 , ksm ( a[ 0 ] , Mod- 2 ) ) , c;
for ( int lim= 2 ; ( lim>> 1 ) < deg; lim<<= 1 ) {
c= a; c. resize ( lim) ; init ( lim<< 1 ) ;
c. resize ( up) ; b. resize ( up) ; NTT ( c) ; NTT ( b) ;
for ( int i= 0 ; i< up; i++ ) Mul ( b[ i] , dec ( 2 , mul ( b[ i] , c[ i] ) ) ) ;
NTT ( b, - 1 ) ; b. resize ( lim) ;
} b. resize ( deg) ; return b;
}
poly integ ( poly a) {
a. pb ( 0 ) ;
for ( int i= a. size ( ) - 1 ; i>= 1 ; i-- ) a[ i] = mul ( a[ i- 1 ] , iv[ i] ) ;
a[ 0 ] = 0 ; return a;
}
poly deriv ( poly a) {
for ( int i= 0 ; i+ 1 < ( int ) a. size ( ) ; i++ ) a[ i] = mul ( a[ i+ 1 ] , i+ 1 ) ;
a. pop_back ( ) ; return a;
}
poly ln ( poly a, int deg) {
a= integ ( inv ( a, deg) * deriv ( a) ) ; a. resize ( deg) ;
return a;
}
poly Exp ( poly a, int deg) {
poly b ( 1 , 1 ) , c;
for ( int lim= 2 ; ( lim>> 1 ) < deg; lim<<= 1 ) {
c= ln ( b, lim) ; Dec ( c[ 0 ] , 1 ) ;
for ( int i= 0 ; i< lim; i++ ) c[ i] = dec ( i< a. size ( ) ?a[ i] : 0 , c[ i] ) ;
b= b* c; b. resize ( lim) ;
} b. resize ( deg) ; return b;
}
int main ( ) {
#ifdef FSYolanda
freopen ( "1.in" , "r" , stdin) ;
#endif
scanf ( "%d%d" , & k, & n) ; ++ n;
NTT_init ( ) ; Fac_init ( n) ; poly f, g;
for ( int i= 0 ; i< n; i++ ) f. pb ( ifc[ i+ 1 ] ) ;
for ( int i= 0 , coe= k+ 1 ; i< n; i++ ) g. pb ( mul ( ifc[ i+ 1 ] , dec ( coe, 1 ) ) ) , Mul ( coe, k+ 1 ) ;
f= g* inv ( f, n) ; f[ 0 ] = 0 ;
for ( int i= 1 ; i< n; i++ ) {
if ( i& 1 ^ 1 ) f[ i] = dec ( 0 , f[ i] ) ;
Mul ( f[ i] , fc[ i- 1 ] ) ;
} f= Exp ( f, n) ;
for ( int i= 1 ; i< n; i++ ) cout<< mul ( fc[ i] , f[ i] ) << '\n' ;
return 0 ;
}