[MdOI R5] Many Minimizations & [ARC163F] Many Increasing Problems 题解
讲下一个思路比较自然的基于自然数幂和的 且复杂度与 几乎无关的做法。
不难发现让我们计数的问题是保序回归 中一条链的情况。这个情况有一个简单的 slope-trick 做法:用堆维护斜率,每次 push
进去两个当前的数,然后 pop
出一个最大值。最终所有数的和减去堆中的数的和就是答案。
有一个来自 ARC128F 经典思维技巧:对于这类弹堆压堆还要求堆中元素和的计数问题,考虑转化成值域为 01 的问题。即活用 的等式。将 的数标成 ,剩余的数标成 。那么如果原先堆中有 个 ,遇到一个 会变成一个 ,遇到一个 会变成 。这就是一个格路游走问题,容易验证最终 的值等于路程中 的个数减去路程中 的个数再加上如果没有对 取 的情况下, 在整个过程中的最小值。
发现唯一难算的就是最后一部分的“最小值之和”。考虑继续运用上面的思维技巧,继续活用等式 ,将 的游走过程看作 到 的游走过程,那么最小值之和(的相反数)可以拆成触碰 这条线的方案数之和。钦定触碰一条线的格路游走就是我们熟悉的反射容斥。我们设原来有 个 ,那么原先终点在 ,如果 则经过那条线的方案数等于到终点 的方案数。
所以对于一个固定的 ,我们需要对以下东西求和:
这个可以预处理 这一行的组合数前缀和简单算出来。
现在考虑对于 你需要依次带入 ,不妨把结果看成一个关于 的多项式,则这个多项式实际上是:
展开 ,容易发现可以用一遍卷积求出 。
最后我们只需要解决 ,相当于要对一个固定的 求出 的自然数幂和 ,可以用多项式求逆求出伯努利数,然后卷一次得到自然数幂和。于是我们就做到复杂度 。
写给自己看的备忘笔记:伯努利数感觉还是直接生成函数定义更好理解。其 EGF 为 。可以对 多项式求逆单 求得。
对于自然数幂和,我们考虑研究其关于 的 EGF:
则:
#include <cstdio> #include <vector> #include <cassert> #include <algorithm> // headers struct poly{/** my poly template **/}; int n,m; const int N=100103; int fac[N],fiv[N]; int arr[N],pre[N]; int coe[N],pw[N]; inline int C(int a,int b){return (ll)fac[a]*fiv[b]%P*fiv[a-b]%P;} void calc(int lim){ pw[0]=1; for(int i=1;i<=lim;++i) pw[i]=(ll)pw[i-1]*m%P; fac[0]=1; for(int i=1;i<=lim;++i) fac[i]=(ll)fac[i-1]*i%P; fiv[lim]=qp(fac[lim]); for(int i=lim;i;--i) fiv[i-1]=(ll)fiv[i]*i%P; } int main(){ n=read();m=read(); calc(n+3);int res=(ll)n*(m-1)%P*pw[n]%P; if(res&1) res+=P; res>>=1; pre[0]=1; for(int i=1;i<=n;++i){ pre[i]=pre[i-1]+C(n,i); if(pre[i]>=P) pre[i]-=P; } poly F(n+1),G(n+1); for(int i=0;i<=n;++i){ if(2*i<=n) F[i]=(pre[i-1]+(ll)C(n,i)*(n-i*2))%P; else F[i]=pre[n-1-i]; F[i]=(ll)F[i]*fac[n-i]%P; } for(int i=0;i<=n;++i) if(i&1) G[i]=fiv[i];else G[i]=P-fiv[i]; G=F*G; for(int i=0;i<=n;++i) coe[i]=(ll)G[i]*pw[n-i]%P*fiv[n-i]%P; F.f.resize(n+2); G.f.resize(n+2); for(int i=0;i<=n+1;++i) F[i]=fiv[i+1]; F=F.inv(n+2); for(int i=0,tt=1;i<=n+1;++i){ G[i]=(ll)tt*fiv[i]%P; tt=(ll)tt*(m+1)%P; } G=F*G; for(int i=0;i<=n;++i) res=(res+(ll)coe[i]*(G[i+1]-F[i+1]+P)%P*fac[i])%P; res-=coe[0]; if(res<0) res+=P; printf("%d\n",res); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现