留待警戒
FFT的时候长度要写的和函数里一样啊XD
瞎扯
这是个第二类斯特林数的理性愉悦颓柿子题目
颓柿子真的是让我hi到不行啦(才没有)
前置芝士
一个公式
[sum_{i=0}^n t^i = frac{t^{n+1}-1}{t-1}
]
第二类斯特林数
第二类斯特林数的是指把n个对象放到m个集合里面的方案数
其递推式是
[S_{n}^{m}=S_{n-1}^{m-1}+mS_{n-1}^{m}
]
容斥原理的得到的通式
[S_n^m=frac{1}{m!}sum_{i=0}^m(-1)^{i}C_{m}^i(m-i)^n
]
颓柿子
题目要求求这样一个式子
[f(n)=sum_{i=0}^nsum_{j=0}^iS_i^j imes2^j imes(j!)
]
然后我们把第二类斯特林数的通式代入进去
[f(n)=sum_{i=0}^nsum_{j=0}^iS_i^j imes2^j imes(j!)
]
得到
[f(n)=sum_{i=0}^nsum_{j=0}^i frac{1}{j!}sum_{k=0}^j(-1)^{k}C_{j}^k(j-k)^i imes2^j imes(j!)\=sum_{i=0}^nsum_{j=0}^ij! imes2^jsum_{k=0}^jfrac{(-1)^k}{k!} imesfrac{(j-k)^i}{(j-k)!}\=sum_{j=0}^nj! imes2^jsum_{k=0}^{j}frac{(-1)^k}{k!} imesfrac{sum_{i=0}^n(j-k)^i}{(j-k)!}
]
如果我们设(F(i)=frac{(-1)^k}{k!}),(G(i)=frac{sum_{i=0}^n(j-k)^i}{(j-k)!}),则很容易就能看出一个卷积的形式,式子变形成
[f(n)=sum_{j=0}^nj! imes 2^j sum_{i=0}^j F(i) imes G(j-i)
]
FFT求后面的式子就行了
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int MOD=998244353LL,G=3,invG=332748118;
int pow(int a,int b){
int ans=1;
while(b){
if(b&1)
ans=(1LL*ans*a)%MOD;
a=(1LL*a*a)%MOD;
b>>=1;
}
return (ans%MOD+MOD)%MOD;
}
void FFT(int *a,int opt,int n){
int lim=0;
while((1<<lim)<n)
lim++;
for(int i=0;i<n;i++){
int t=0;
for(int j=0;j<lim;j++)
if((i>>j)&1)
t|=(1<<(lim-j-1));
if(i<t)
swap(a[t],a[i]);
}
for(int i=2;i<=n;i<<=1){
int len=i/2;
int tmp=pow((opt)?G:invG,(MOD-1)/i);
for(int j=0;j<n;j+=i){
int arr=1;
for(int k=j;k<j+len;k++){
int t=(a[k+len]*arr)%MOD;
a[k+len]=((a[k]-t)%MOD+MOD)%MOD;
a[k]=(a[k]+t)%MOD;
arr=(arr*tmp)%MOD;
}
}
}
if(opt==0){
int invn=pow(n,MOD-2);
for(int i=0;i<n;i++)
a[i]=(a[i]*invn)%MOD;
}
}
int a[300100],b[300100],n;
int jc[300100],inv[300100];
void init(void){
jc[0]=inv[0]=1;
for(int i=1;i<=n;i++){
jc[i]=jc[i-1]*i%MOD;
inv[i]=pow(jc[i],MOD-2);
}
}
int f(int x){
return ((((x&1)?-1:1)%MOD+MOD)%MOD*(inv[x]))%MOD;
}
int g(int x){
if(x==1)
return n+1;
return ((((pow(x,n+1)-1)%MOD+MOD)%MOD)*pow(x-1+MOD,MOD-2)%MOD)*inv[x]%MOD;
}
signed main(){
scanf("%lld",&n);
// printf("n=%d
",n);
init();
for(int i=0;i<=n;i++)
a[i]=f(i),b[i]=g(i);
// for(int i=0;i<=n;i++)
// printf("f(%lld)=%lld g(%lld)=%lld
",i,a[i],i,b[i]);
int lx=1;
while(lx<=(n+n))
lx<<=1;
FFT(a,1,lx);
FFT(b,1,lx);
for(int i=0;i<lx;i++)
a[i]=(a[i]*b[i])%MOD;
FFT(a,0,lx);
// for(int i=0;i<=n;i++)
// printf("f*g(%lld)=%lld
",i,a[i]);
int ans=0;
for(int i=0,j=1;i<=n;i++,j=(j+j)%MOD)
ans=(ans+j*jc[i]%MOD*a[i]%MOD)%MOD;
printf("%lld
",ans);
return 0;
}