! TJOI/HEOI2016求和

[ans=f(n)=sum_{i=0}^nsum_{j=0}^iS_i^j*2^j*j!,n1e5 ]

第二类斯特林数

[S_m^n=sum_{i=0}^nfrac{(-1)^{n-i}*i^m}{i!(n-i)!} ]

[f(n)=sum_{i=0}^nsum_{j=0}^n2^j*j!sum_{k=0}^jfrac{(-1)^{j-k}*k^i}{k!(j-k)!} ]

[f(n)=sum_{j=0}^n2^jj!sum_{k=0}^j(frac{(-1)^{j-k}}{(j-k)!})(frac{sum_{i=0}^nk^i}{k!}) ]

[sum_{i=0}^nk^i=frac{k^{n+1}-1}{k-1} ]

于是可以愉快地卷积了!时间复杂度(O(nlogn))

还有(O(n))的做法,还不是很会

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
#define ll long long
const int N=1e5+4,g=3,mod=998244353; 
inline int ksm(int x,int r){
	int ret=1;
	for(int i=0;(1<<i)<=r;i++){
		if((1<<i)&r)ret=(ll)ret*x%mod;
		x=(ll)x*x%mod;
	}
	return ret;
}
int n,A[N<<2],B[N<<2],fac[N],inv[N],rev[N<<2]; 
inline void ntt(int *a,int fl,int lim,int len){
	for(int i=0;i<len;i++){
		rev[i]=(rev[i>>1]>>1)|((i&1)<<lim-1);
		if(i<rev[i])swap(a[i],a[rev[i]]);
	}
	for(int mid=1,tmp,x,u,v;mid<len;mid<<=1){
		tmp=ksm(g,(mod-1)/(mid<<1));
		if(fl==-1)tmp=ksm(tmp,mod-2);
		for(int i=0;i<len;i+=(mid<<1)){
			x=1;
			for(int j=0;j<mid;j++,x=(ll)x*tmp%mod){
				u=a[i+j];v=(ll)a[i+j+mid]*x%mod;
				a[i+j]=(u+v)%mod;a[i+j+mid]=(u-v+mod)%mod; 
			}
		}
	}
	if(fl==-1)for(int i=0,tmp=ksm(len,mod-2);i<len;i++)
		a[i]=(ll)a[i]*tmp%mod;
}
int main(){
	n=read();
	fac[0]=fac[1]=inv[0]=inv[1]=1;
	for(int i=2;i<=n;i++)fac[i]=(ll)fac[i-1]*i%mod;
	inv[n]=ksm(fac[n],mod-2);
	for(int i=n-1;i>1;i--)inv[i]=(ll)inv[i+1]*(i+1)%mod;
	for(int i=0;i<=n;i++){
		A[i]=(ll)(i&1?mod-1:1)*inv[i]%mod;
		B[i]=(ll)inv[i]*(ksm(i,n+1)+mod-1)%mod*ksm((i+mod-1)%mod,mod-2)%mod;
	}
	B[1]=n+1;//!
	int lim=0,len=1,ans=0;
	while(len<=(n<<1)){lim++;len<<=1;}
	ntt(A,1,lim,len);ntt(B,1,lim,len);
	for(int i=0;i<len;i++)A[i]=(ll)A[i]*B[i]%mod;
	ntt(A,-1,lim,len);
	for(int i=0,mi2=1;i<=n;i++,mi2=(mi2<<1)%mod)
		ans=((ll)mi2*fac[i]%mod*A[i]+ans)%mod;
	cout<<ans;
	return (0-0);
}
原文地址:https://www.cnblogs.com/aurora2004/p/12745664.html