题目大意
分析
首先你必须要知道第二类斯特林数的通项公式,也可以自己推,但这时你也需要知道第二类斯特林数的含义是什么,真坑。。。
然后化简成卷积的形式就可以了,上NTT。
额。。。为什么我不写呢?
一个是因为我自己也不是很会推
另外是我并不是很会编辑用数学公式
(当然主要原因是第一个咯)
其实我只是想打个NTT而已啦。
代码
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=300000+1005,mod=998244353;
int n,lim,l,r[maxn<<1];
LL f[maxn],g[maxn],h[maxn];
LL qkpow(LL a,LL p)
{
LL t=1,tt=a%mod;
while(p)
{
if(p&1)t=t*tt%mod;
tt=tt*tt%mod;
p>>=1;
}
return t;
}
void Init()
{
LL tmp=1;
g[0]=1,h[0]=1;
for(int i=1;i<=lim;i++)
{
tmp=tmp*i%mod;
g[i]=-g[i-1]*qkpow(i,mod-2)%mod;
h[i]=(qkpow(i,lim+1)-1+mod)%mod*qkpow(i-1,mod-2)%mod*qkpow(tmp,mod-2)%mod;
}
h[1]=lim+1;
int k=lim*2;
for(n=1;n<k;n<<=1)l++;
for(int i=0;i<n;i++)r[i]=((r[i>>1]>>1)|((i&1)<<(l-1)));
}
void NTT(LL *c,int f)
{
for(int i=0;i<n;i++)if(i<r[i])swap(c[i],c[r[i]]);
for(int i=1;i<n;i<<=1)
{
LL wn=qkpow(3,(mod-1)/(i<<1)),x,y;
for(int j=0;j<n;j+=(i<<1))
{
LL w=1;
for(int k=0;k<i;k++,w=w*wn%mod)
{
x=c[j+k],y=w*c[i+j+k]%mod;
c[j+k]=(x+y)%mod,c[i+j+k]=(x-y+mod)%mod;
}
}
}
if(f==-1){
reverse(c+1,c+n);
LL tmp=qkpow(n,mod-2);
for(int i=0;i<n;i++)c[i]=c[i]*tmp%mod;
}
}
LL ans;
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&lim);
Init();
NTT(g,1);NTT(h,1);
for(int i=0;i<n;i++)f[i]=g[i]*h[i]%mod;
NTT(f,-1);
LL t1=1,t2=1;
ans=f[0];
for(int i=1;i<=lim;i++)
{
t1=t1*2%mod;
t2=t2*i%mod;
ans=(ans+t1*t2%mod*f[i])%mod;
}
printf("%lld\n",ans);
return 0;
}