题面
设
B
i
B_i
Bi 为伯努利数的第
i
i
i 项。伯努利数有许多定义方法,这里定义
∑
i
=
0
B
i
i
!
x
i
=
x
1
−
e
−
x
\sum_{i=0}\frac{B_i}{i!}x^i=\frac{x}{1-e^{-x}}
∑i=0i!Bixi=1−e−xx。设
G
n
(
x
)
=
∑
i
=
0
S
i
(
n
)
n
!
x
i
G_n(x)=\sum_{i=0}\frac{S_i(n)}{n!}x^i
Gn(x)=∑i=0n!Si(n)xi,带入
S
i
(
n
)
S_i(n)
Si(n) 得到:
G
n
(
x
)
=
∑
i
=
0
∑
j
=
0
n
(
j
x
)
i
i
!
G_n(x)=\sum_{i=0}\sum_{j=0}^n\frac{(jx)^i}{i!}
Gn(x)=∑i=0∑j=0ni!(jx)i
利用
e
x
e^x
ex 的泰勒展开:
G
n
(
x
)
=
∑
i
=
0
n
e
i
x
G_n(x)=\sum_{i=0}^n e^{ix}
Gn(x)=∑i=0neix
利用等比数列求和公式:
G
n
(
x
)
=
∑
i
=
0
n
e
−
x
−
e
n
x
e
−
x
−
1
G_n(x)=\sum_{i=0}^n\frac{e^{-x}-e^{nx}}{e^{-x}-1}
Gn(x)=∑i=0ne−x−1e−x−enx
根据伯努利数的定义:
G
n
(
x
)
=
1
−
∑
i
=
0
B
i
i
!
x
i
−
1
(
1
−
e
(
n
+
1
)
x
)
G_n(x)=1-\sum_{i=0}\frac{B_i}{i!}x^{i-1}(1-e^{(n+1)x})
Gn(x)=1−∑i=0i!Bixi−1(1−e(n+1)x)
再次泰勒展开:
G
n
(
x
)
=
1
+
∑
i
=
0
B
i
i
!
x
i
−
1
∑
j
=
1
(
n
x
)
j
j
!
G_n(x)=1+\sum_{i=0}\frac{B_i}{i!}x^{i-1}\sum_{j=1}\frac{(nx)^j}{j!}
Gn(x)=1+∑i=0i!Bixi−1∑j=1j!(nx)j
做多项式乘法:
G
n
(
x
)
=
1
+
∑
i
=
0
∑
j
=
0
i
B
j
n
p
+
1
−
j
j
!
(
i
+
1
−
j
)
!
x
i
G_n(x)=1+\sum_{i=0}\sum_{j=0}^i \frac{B_j n^{p+1-j}}{j!(i+1-j)!} x^i
Gn(x)=1+∑i=0∑j=0ij!(i+1−j)!Bjnp+1−jxi
阶乘转化为组合数:
G
n
(
x
)
=
1
+
∑
i
=
0
x
i
i
!
1
p
+
1
∑
j
=
0
i
(
p
+
1
j
)
B
j
n
p
+
1
−
j
G_n(x)=1+\sum_{i=0}\frac{x^i}{i!}\frac{1}{p+1}\sum_{j=0}^i \binom{p+1}{j}B_j n^{p+1-j}
Gn(x)=1+∑i=0i!xip+11∑j=0i(jp+1)Bjnp+1−j
代回原式:
∑
i
=
0
n
i
j
=
[
j
=
0
]
+
1
j
+
1
∑
k
=
0
j
(
p
+
1
j
)
B
j
n
p
+
1
−
j
\sum_{i=0}^n i^j=[j=0]+\frac{1}{j+1}\sum_{k=0}^j \binom{p+1}{j}B_j n^{p+1-j}
∑i=0nij=[j=0]+j+11∑k=0j(jp+1)Bjnp+1−j
因此伯努利数可以用于求自然数幂和。
回归原题:
c
i
=
∑
j
=
i
−
1
n
a
j
j
+
1
(
j
+
1
j
+
1
−
i
)
B
j
+
1
−
i
c_i=\sum_{j=i-1}^n\frac{a_j}{j+1}\binom{j+1}{j+1-i}B_{j+1-i}
ci=∑j=i−1nj+1aj(j+1−ij+1)Bj+1−i
拆掉组合数:
c
i
i
!
=
∑
j
=
i
−
1
n
a
j
j
!
B
j
+
1
−
i
(
j
+
1
−
i
)
!
c_i i!=\sum_{j=i-1}^n\frac{a_j j! B_{j+1-i}}{(j+1-i)!}
cii!=∑j=i−1n(j+1−i)!ajj!Bj+1−i
显然可以多项式卷积求出
c
c
c,其中
c
0
c_0
c0 需要特殊处理,即
c
0
=
a
0
c_0=a_0
c0=a0。
根据伯努利数的生成函数,可以利用多项式求逆求出。
时间复杂度
O
(
n
log
2
n
)
O(n \log_2n)
O(nlog2n),空间复杂度
O
(
n
)
O(n)
O(n)
#include<stdio.h>
#define R register int
#define L long long
#define I inline
#define N 524288
#define M 250003
#define P 998244353
int a[N],b[N],c[N],fac[M],invf[M];
I void Swap(int&x,int&y){
int tem=x;
x=y;
y=tem;
}
I int Add(int x,int y){
x+=y;
if(x<0){
return x+P;
}
return x>=P?x-P:x;
}
I int PowMod(int x,int y){
int s=1;
while(y!=0){
if((y&1)==1){
s=(L)s*x%P;
}
x=(L)x*x%P;
y>>=1;
}
return s;
}
I void NTT(int*A,const int len,const short type){
int tem=0;
for(R i=0;i!=len;i++){
if(i<tem){
Swap(A[i],A[tem]);
}
R j=len;
do{
j>>=1;
tem^=j;
}while(tem<j);
}
static int w[N];
w[0]=1;
for(R i=1;i!=len;i<<=1){
tem=i<<1;
int omg=PowMod(3,P-1+(P-1)*type/tem);
for(R j=1;j!=i;j++){
w[j]=(L)w[j-1]*omg%P;
}
for(R j=0;j!=len;j+=tem){
for(R k=j;k!=i+j;k++){
int t1=A[k],t2=(L)A[i+k]*w[k-j]%P;
A[k]=Add(t1,t2);
A[i+k]=Add(t1,-t2);
}
}
}
if(type==-1){
tem=PowMod(len,P-2);
for(R i=0;i!=len;i++){
A[i]=(L)A[i]*tem%P;
}
}
}
I void PolyInverse(int*A,int*B,const int len){
static int tem[N];
B[0]=PowMod(A[0],P-2);
for(R i=1;i!=len;i<<=1){
int p=i<<2;
NTT(B,p,1);
for(R j=0;j!=i<<1;j++){
tem[j]=A[j];
}
NTT(tem,p,1);
for(R j=0;j!=p;j++){
B[j]=(L)B[j]*(P+2-(L)tem[j]*B[j]%P)%P;
}
NTT(B,p,-1);
for(R j=i<<1;j!=p;j++){
B[j]=tem[j]=0;
}
}
for(R i=0;i!=len<<1;i++){
tem[i]=0;
}
}
int main(){
fac[0]=1;
int n,x,len=1;
scanf("%d",&n);
for(R i=1;i!=n+3;i++){
fac[i]=(L)fac[i-1]*i%P;
}
for(R i=0;i<=n;i++){
scanf("%d",&x);
a[n-i]=(L)x*fac[i]%P;
}
printf("%d",a[n]);
n+=2;
invf[n]=PowMod(fac[n],P-2);
for(R i=n;i!=0;i--){
invf[i-1]=(L)invf[i]*i%P;
}
while(len<n){
len<<=1;
}
for(R i=0;i<=n;i++){
c[i]=invf[i+1];
if((i&1)==1){
c[i]=P-c[i];
}
}
PolyInverse(c,b,len);
len<<=1;
NTT(a,len,1);
NTT(b,len,1);
for(R i=0;i!=len;i++){
a[i]=(L)a[i]*b[i]%P;
}
NTT(a,len,-1);
for(R i=1;i!=n;i++){
printf(" %d",(L)invf[i]*a[n-i-1]%P);
}
return 0;
}