求 (sum_{i=0}^{n}sum_{j=0}^{i}S(i,j) imes 2^j imes (j!))
不妨将式子化为 (sum_{i=0}^{n}sum_{j=0}^{n}S(i,j) imes 2^j imes (j!)) (反正如果 (j>i) 的话 (S(i,j)=0))
其中 (S(i,j)) 为第二类斯特林数.
一般做这种推式子题时如果题面给的式子本身很简洁,那么八成是要把里面的东西暴力展开了.
展开斯特林数:(S(n,m)=frac{1}{m!}sum_{i=0}^{m}(-1)^iinom{m}{i}(m-i)^n)
原式可化为 (sum_{i=0}^{n}sum_{j=0}^{n}2^j(j!)sum_{k=0}^{j}frac{(-1)^k}{k!}frac{(j-k)^i}{(j-k)!})
考虑将 (j) 移到前面,得 (sum_{j=0}^{n}2^j(j!)sum_{k=0}^{j}frac{(-1)^k}{k!}frac{sum_{i=0}^{n}(j-k)^i}{(j-k)!})
然后上面那个用等比数列求和公式处理,为 (sum_{j=0}^{n}2^j(j!)sum_{k=0}^{j}frac{(-1)^k}{k!}frac{(j-k)^{n+1}-1}{(j-k-1)(j-k)!})
后面那个是一个卷积的形式,用 NTT 加速即可(等比数列要特判一下公比为 1 的情况)
#include <bits/stdc++.h>
#define G 3
#define N 200001
#define ll long long
#define mod 998244353
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
ll qpow(ll x,ll y)
{
ll tmp=1ll;
while(y)
{
if(y&1) tmp=tmp*x%mod;
x=x*x%mod, y>>=1;
}
return tmp;
}
ll Inv(ll x) { return qpow(x,mod-2); }
void NTT(ll *a,int len,int op)
{
int i,j,mid,k;
for(i=k=0;i<len;++i)
{
if(i>k) swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(mid=1;mid<len;mid<<=1)
{
ll wn=qpow(G,(mod-1)/(mid<<1));
if(op==-1) wn=Inv(wn);
for(i=0;i<len;i+=mid<<1)
{
ll w=1ll;
for(j=0;j<mid;++j)
{
ll x=a[i+j],y=w*a[i+j+mid]%mod;
a[i+j]=(x+y)%mod, a[i+j+mid]=(x-y+mod)%mod;
w=w*wn%mod;
}
}
}
if(op==-1)
{
ll rev=Inv(len);
for(i=0;i<len;++i) a[i]=a[i]*rev%mod;
}
}
ll fac[N],inv[N],f[N<<1],g[N<<1];
int main()
{
// setIO("input");
int i,j,n,limit;
scanf("%d",&n);
fac[0]=inv[0]=1ll;
for(i=1;i<N;++i) fac[i]=fac[i-1]*1ll*i%mod, inv[i]=Inv(fac[i]);
f[0]=1ll, g[0]=1ll, g[1]=n+1;
for(i=1;i<=n;++i) f[i]=(qpow(-1,i)*inv[i]+mod)%mod;
for(i=2;i<=n;++i) g[i]=(qpow(i,n+1)-1+mod)%mod*inv[i]%mod*Inv(i-1)%mod;
for(limit=1;limit<=2*n;limit<<=1);
NTT(f,limit,1), NTT(g,limit,1);
for(i=0;i<limit;++i) f[i]=f[i]*g[i]%mod;
NTT(f,limit,-1);
ll ans=0ll;
for(i=0;i<=n;++i) (ans+=qpow(2,i)*fac[i]%mod*f[i]%mod)%=mod;
printf("%lld
",ans);
return 0;
}