题目描述
在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心。
现在他想计算这样一个函数的值:
f(n)=∑i=0n∑j=0iS(i,j)×j!×2j
f
(
n
)
=
∑
i
=
0
n
∑
j
=
0
i
S
(
i
,
j
)
×
j
!
×
2
j
S(i, j)表示第二类斯特林数
你能帮帮他吗?
输出f(n)。由于结果会很大,输出f(n)对998244353(7 × 17 × 223 + 1)取模的结果即可
Solution
首先j的枚举上界可以直接变成n,原因可以考虑当i< j时第二类斯特林数为0
第二类斯特林数可以拆,那么就是
∑i=0n∑j=0n2j×j!∑k=0j(−1)k×C(j,k)×(j−k)i
∑
i
=
0
n
∑
j
=
0
n
2
j
×
j
!
∑
k
=
0
j
(
−
1
)
k
×
C
(
j
,
k
)
×
(
j
−
k
)
i
组合数也可以拆,那么就是
∑i=0n∑j=0n2j×j!∑k=0j(−1)kk!×(j−k)i(j−k)!
∑
i
=
0
n
∑
j
=
0
n
2
j
×
j
!
∑
k
=
0
j
(
−
1
)
k
k
!
×
(
j
−
k
)
i
(
j
−
k
)
!
把最外面的∑拉到最里面有
∑j=0n2j×j!∑k=0j(−1)kk!×∑ni=0(j−k)i(j−k)!
∑
j
=
0
n
2
j
×
j
!
∑
k
=
0
j
(
−
1
)
k
k
!
×
∑
i
=
0
n
(
j
−
k
)
i
(
j
−
k
)
!
后半部分实际上是个卷积,i的∑实际上是等比数列求和,NTT一下求解就好了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const int MOD=998244353;
const int N=300005;
const int G=3;
int fac[N],a[N],b[N],c[N];
int rev[N],inv[N];
int len,lg,ny;
LL ksm(LL x,LL dep) {
if (dep==0) return 1;
if (dep==1) return x;
LL tmp=ksm(x,dep/2);
if (dep&1) return tmp*tmp%MOD*x%MOD;
return tmp*tmp%MOD;
}
void DFT(int *a,int f) {
rep(i,0,len-1) if (i<rev[i]) std:: swap(a[rev[i]],a[i]);
for (int i=1;i<len;i*=2) {
int wn;
if (f==1) wn=ksm(G,(MOD-1)/i/2);
else wn=ksm(G,MOD-1-(MOD-1)/i/2);
for (int j=0;j<len;j+=i*2) {
int w=1;
for (int k=0;k<i;k++) {
int u=a[j+k],v=(LL)a[j+k+i]*w%MOD;
a[j+k]=(u+v)%MOD;
a[j+k+i]=(u-v)%MOD;
w=(LL)w*wn%MOD;
}
}
}
if (f==-1) rep(i,0,len-1) a[i]=(LL)a[i]*ny%MOD;
}
void pre_work(int n) {
fac[0]=1; rep(i,1,n) fac[i]=(LL)fac[i-1]*i%MOD;
inv[0]=1; rep(i,1,n) inv[i]=ksm(fac[i],MOD-2);
for (len=1;len<=n*2;len<<=1,lg++);
rep(i,0,len-1) rev[i]=(rev[i/2]/2)|((i&1)<<(lg-1));
ny=ksm(len,MOD-2);
}
int main(void) {
int n; scanf("%d",&n); pre_work(n);
rep(i,0,n) a[i]=((i&1)?(-1):(1))*inv[i];
a[0]=1; b[0]=1; b[1]=n+1;
rep(i,2,n) b[i]=(LL)((LL)(ksm(i,n+1)-1)*inv[i]%MOD*ksm(i-1,MOD-2)%MOD+MOD)%MOD;
rep(i,0,n) printf("%d %d\n", a[i],b[i]);
DFT(a,1); DFT(b,1);
rep(i,0,len-1) a[i]=(LL)a[i]*b[i]%MOD;
DFT(a,-1);
LL ans=0; rep(i,0,n) ans=(ans+(LL)a[i]*fac[i]%MOD*ksm(2,i)%MOD)%MOD;
printf("%lld\n", (ans+MOD)%MOD);
return 0;
}