bzoj4555:[Tjoi2016&Heoi2016]求和

传送门

首先我们需要知道第二类斯特林数的通项公式

\[S(n,m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^k\binom{m}{k}(m-k)^n \]

然后我们就可以将题目给的式子里的第二类斯特林数拆开

\[f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}\frac{1}{j!}\sum_{k=0}^{j}(-1)^k\binom{j}{k}(j-k)^i2^j(j!)\\ f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}2^j\sum_{k=0}^{j}(-1)^k\binom{j}{k}(j-k)^i\\ \]

然后发现这个式子貌似做不下去了,然后考虑对于\(j>i\)\(S(i,j)\)都是没有意义的

\[f(n)=\sum_{i=0}^{n}\sum_{j=0}^{n}2^j\sum_{k=0}^{j}(-1)^k\binom{j}{k}(j-k)^i\\ \]

然后把组合数拆开

\[f(n)=\sum_{i=0}^{n}\sum_{j=0}^{n}2^j\sum_{k=0}^{j}(-1)^k\frac{j!}{k!(j-k)!}(j-k)^i\\ \]

然后调换一下\(\sum\)

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

\[f(i)=\frac{(-1)^i}{i!}\\ g(i)=\frac{\sum_{j=0}^{n}i^j}{i!} \]

那么

\[f(n)=\sum_{j=0}^{n}2^jj!\sum_{k=0}^{j}f(k)g(j-k) \]

可以发现后面是一个卷积的形式,可以用ntt快速计算,然后这个题就做完了

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
void read(int &x){
	char ch;bool ok;
	for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
	for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
#define rg register
const int maxn=4e5+10,mod=998244353,g=3,gi=332748118;
int n,a[maxn],b[maxn],m,fac[maxn],inv[maxn],len,ans,r[maxn];
int mul(int x,int y){return 1ll*x*y-1ll*x*y/mod*mod;}
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int del(int x,int y){return x-y<0?x-y+mod:x-y;}
int mi(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=mul(ans,a);
		b>>=1,a=mul(a,a);
	}
	return ans;
}
void ntt(int *a,int f){
	for(rg int i=0;i<n;i++)if(r[i]>i)swap(a[i],a[r[i]]);
	for(rg int i=1;i<n;i<<=1){
		int wn=mi(f?g:gi,(mod-1)/(i<<1));
		for(rg int j=0;j<n;j+=i<<1){
			int w=1;
			for(rg int k=0;k<i;k++){
				int x=a[j+k],y=mul(w,a[i+j+k]);
				a[j+k]=add(x,y),a[j+k+i]=del(x,y),w=mul(w,wn);
			}
		}
	}
	if(f)return ;int inv=mi(n,mod-2);
	for(rg int i=0;i<n;i++)a[i]=mul(a[i],inv);
}
int sum(int q){return q==1?n+1:mul(del(mi(q,n+1),1),mi(del(q,1),mod-2));}
int main(){
	read(n);fac[0]=1;
	for(rg int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
	inv[n]=mi(fac[n],mod-2);
	for(rg int i=n-1;i>=0;i--)inv[i]=mul(inv[i+1],i+1);
	for(rg int i=0;i<=n;i++)a[i]=mul((i&1?mod-1:1),inv[i]);
	for(rg int i=0;i<=n;i++)b[i]=mul(sum(i),inv[i]);
	m=n+n;for(n=1;n<=m;n<<=1)len++;m=m/2;
	for(rg int i=0;i<=n;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
    ntt(a,1),ntt(b,1);
	for(rg int i=0;i<=n;i++)a[i]=mul(a[i],b[i]);
	ntt(a,0);
	for(rg int i=0;i<=m;i++)ans=add(ans,mul(mi(2,i),mul(fac[i],a[i])));
	printf("%d\n",ans);
}

posted @ 2019-04-24 12:05  蒟蒻--lichenxi  阅读(118)  评论(0编辑  收藏  举报