【题解】P5364 [SNOI2017]礼物

提供一个讨论区有人提出但没细讲的斯特林数做法,复杂度 O(k2) 且可优化到 O(klogk)

前置知识:第二类斯特林数的常用性质。

题目传送门

下文中为了方便设 m=n1

首先发现题目让我们求 i=1m2mi×ik+nk,这个式子的推导别的题解都有写我就不写了。

为方便,考虑求 i=0m2mi×ik

可以发现它和常见的第二类斯特林数应用中的求自然数 k 次幂和很像,所以考虑用同样的方法做。

代入第二类斯特林数的性质式子 ik=j=0k{kj}j!(ij),推一波式子:

ans=i=0m2mi×ik=i=0m2mij=0k{kj}j!(ij)=j=0k{kj}j!i=0m2mi(ij)=j=0k{kj}j!i=jm2mi(ij)

g(p)=i=pm2mi(ip),这个式子怎么求呢?考虑递推搞出下一项:

g(p)=i=pm2mi(ip)=i=p+1m2mi(ip)+2mp=i=p+1m2mi×((i+1p+1)(ip+1))+2mp=i=p+1m2mi×(i+1p+1)i=p+1m2mi(ip+1)+2mp=i=p+2m+12mi+1(ip+1)g(p+1)+2mp=(m+1p+1)g(p+1)+2i=p+2m2mi(ip+1)+2×2m(p+1)=(m+1p+1)g(p+1)+2i=p+1m2mi(ip+1)=(m+1p+1)+g(p+1)

反过来,有 g(p)=g(p1)(m+1p)=g(p1)(np)

于是求出边界 g(0)=i=0m2mi(i0)=i=0m2i=2m+11=2n1 然后递推即可求出 g

所以只要枚举 j,算出 j=0k{kj}j!g(j) 即可算出答案。

复杂度 O(k2),瓶颈在于预处理第二类斯特林数,用 NTT 卷积求一行的第二类斯特林数可优化到 O(klogk)

主要部分代码(马蜂较诡异,勿喷):

inline ll md(ll x){return x<0?x+mod:x;}
inline ll qpow(ll d,ll z){
	ll res=1ll;
	for(;z;z>>=1ll,d=d*d%mod) if(z&1ll) res=res*d%mod;
	return res;
}

signed main(){
	ll n=read();int k=read();
	inv[0]=inv[1]=stl[1][1]=1ll;
	for(re int i=2;i<=k;++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	for(re int i=2;i<=k;++i) for(re int j=1;j<=i;++j) stl[i][j]=(stl[i-1][j-1]+j*stl[i-1][j])%mod;
	ll f=1ll,g=md(qpow(2ll,n)-1),c=1ll,ans=qpow(n%=mod,k);
	for(re int j=0;j<=k;++j,f=f*j%mod,g=md(g-(c=c*(n-j+1ll)%mod*inv[j]%mod))) ans=(ans+stl[k][j]*f%mod*g)%mod;
	printf("%lld\n",ans);
	return 0;
}
posted @   WhaleAtCola  阅读(92)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示