提供一个讨论区有人提出但没细讲的斯特林数做法,复杂度 O(k2) 且可优化到 O(klogk)。
前置知识:第二类斯特林数的常用性质。
题目传送门
下文中为了方便设 m=n−1。
首先发现题目让我们求 ∑mi=12m−i×ik+nk,这个式子的推导别的题解都有写我就不写了。
为方便,考虑求 ∑mi=02m−i×ik。
可以发现它和常见的第二类斯特林数应用中的求自然数 k 次幂和很像,所以考虑用同样的方法做。
代入第二类斯特林数的性质式子 ik=∑kj=0{kj}j!(ij),推一波式子:
ans=m∑i=02m−i×ik=m∑i=02m−ik∑j=0{kj}j!(ij)=k∑j=0{kj}j!m∑i=02m−i(ij)=k∑j=0{kj}j!m∑i=j2m−i(ij)
设 g(p)=∑mi=p2m−i(ip),这个式子怎么求呢?考虑递推搞出下一项:
g(p)=m∑i=p2m−i(ip)=m∑i=p+12m−i(ip)+2m−p=m∑i=p+12m−i×((i+1p+1)−(ip+1))+2m−p=m∑i=p+12m−i×(i+1p+1)−m∑i=p+12m−i(ip+1)+2m−p=m+1∑i=p+22m−i+1(ip+1)−g(p+1)+2m−p=(m+1p+1)−g(p+1)+2m∑i=p+22m−i(ip+1)+2×2m−(p+1)=(m+1p+1)−g(p+1)+2m∑i=p+12m−i(ip+1)=(m+1p+1)+g(p+1)
反过来,有 g(p)=g(p−1)−(m+1p)=g(p−1)−(np)。
于是求出边界 g(0)=∑mi=02m−i(i0)=∑mi=02i=2m+1−1=2n−1 然后递推即可求出 g。
所以只要枚举 j,算出 ∑kj=0{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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下