題目連接php
\(Description\)
求
\[\sum_{i=0}^n\sum_{j=0}^iS(i,j)2^jj!\]對998244353取模後的結果。spa
\(n<=10^5\)code
\(Solution\)
\(S(i,j)\)在這裏就很是礙事,怎麼把它寫成一個多項式的形式呢?
第二類斯特林數還有一種容斥的寫法
\[S(n,m)=\frac{1}{m!}\sum_{i=0}^m(-1)^iC_m^i(m-i)^n\]
把它帶到要求的式子裏去
\[\sum_{i=0}^n\sum_{j=0}^i2^jj!\frac{1}{j!}\sum_{k=0}^j(-1)^k\frac{j!}{k!(j-k)!}(j-k)^i\]
\[=\sum_{j=0}^n2^jj!\sum_{k=0}^j\frac{(-1)^k}{k!}\frac{\sum_{i=0}^n(j-k)^i}{(j-k)!}\]
最後是個等比數列求和
\[\sum_{j=0}^n2^jj!\sum_{k=0}^j\frac{(-1)^k}{k!}\frac{(j-k)^{n+1}-1}{(j-k-1)(j-k)!}\]
後邊的求和直接\(NTT\)作。ip
#include<complex> #include<cstdio> using namespace std; const int mod=998244353,R=3; const int N=3e5+7; int n,invR; int F[N],G[N],fac[N],finv[N],r[N]; int qread() { int x=0; char ch=getchar(); while(ch<'0' || ch>'9')ch=getchar(); while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } int Fpow(long long b,int p) { long long res=1; for(;p;p>>=1,b=b*b%mod) if(p&1)res=res*b%mod; return res; } void NTT(int *a,int lim,int opt) { for(int i=1;i<lim;i++) if(i<r[i])swap(a[i],a[r[i]]); for(int i=2;i<=lim;i<<=1) { int mid=i>>1,Wn=Fpow(~opt?R:invR,(mod-1)/i),t; for(int j=0;j<lim;j+=i) { long long w=1; for(int k=j;k<j+mid;k++,w=w*Wn%mod) { t=1ll*w*a[k+mid]%mod; a[k+mid]=(a[k]-t+mod)%mod;a[k]=(a[k]+t)%mod; } } } if(opt==-1)for(int i=0,inv=Fpow(lim,mod-2);i<lim;i++)a[i]=1ll*a[i]*inv%mod; } int main() { scanf("%d",&n); fac[0]=finv[0]=1; for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod; finv[n]=Fpow(fac[n],mod-2); for(int i=n-1;i;i--) finv[i]=1ll*finv[i+1]*(i+1)%mod; for(int i=2;i<=n;i++) F[i]=1ll*(Fpow(i,n+1)-1)*Fpow(i-1,mod-2)%mod*finv[i]%mod; F[0]=1;F[1]=n+1; for(int i=0;i<=n;i++) G[i]=((i&1?-1:1)*finv[i]+mod)%mod; int lim=1,l=-1; invR=Fpow(R,mod-2); while(lim<=n+n)lim<<=1,l++; for(int i=1;i<lim;i++)r[i]=(r[i>>1]>>1)|((i&1)<<l); NTT(F,lim,1);NTT(G,lim,1); for(int i=0;i<lim;i++) F[i]=1ll*F[i]*G[i]%mod; NTT(F,lim,-1); int ans=0; for(int i=0,p=1;i<=n;i++,p=(p<<1)%mod) ans=(ans+1ll*p*fac[i]%mod*F[i]%mod)%mod; printf("%d\n",ans); return 0; }