《浅谈一类最小公倍数的求和问题及其拓展》学习笔记
大致是要解决一个如下的问题
有 \(n\) 个 \(k\) 维向量,第 \(i\) 个为 \(V_i=\{v_{i,1},v_{i,2},...,v_{i,k}\}\) ,定义 \(\vec{a} \le \vec{b}\) 当且仅当 \(\vec{a}\) 的每一维都小于 \(\vec{b}\) , \(\max(\vec{a},\vec{b})\) 这个向量的每一维都是 \(\vec{a}\) 与 \(\vec{b}\) 的 \(\max\) ,然后要计算
其中 \(F(V)=\prod\limits_{i=1}^{k}f_i(v_i)\) , \(\forall x \in (0,+\infty) \cap \mathbb{Z},f_i(x) \in \mathbb{Z}^{+}\)
保证了 \(V_i\) 每一维有一些限制,在最开始的问题中为 \(v_{i,j}\) 小于等于 \(\log_{p_j} i\) , \(p_j\) 是第 \(j\) 个质数
我会暴力 \(map\) 维护状态!貌似可以过 \(50\) ,很可以,可惜上面那个限制下可以做到 \(n \le 2000\) ,差的比较远
但是我们还是先记个 \(\text{DP}\) ,令 \(g_{i,V}\) 表示转移到了第 \(i\) 个,\(\max\) 的向量为 \(V\) 的 \(a_i\) 乘积之和
首先就有限制 \(V \le pre_i=\max\limits_{j=1}^{i} V_j\) ,原因显然
观察 \(g_{i,*}\) 与答案之间有什么关系,可以发现有
记 \(g_{i,V}\) 后面那么长的式子为 \(s_{i,V}\) ,即有 \(ans=\sum\limits_{V} g_{i,V}s_{i,V}\)
这个时候可以发现一个性质,记 \(suf_{i+1}=\max\limits_{j=i+1}^{n} V_j\) ,那么若 \(V\) 的有一维 \(v_j > suf_{i,j}\) ,则
论文里面有证明,感性理解一下也很对,因为 \(v_j>suf_{i+1,j}\) 所以 \(\max\{\cdots\}\) 的第 \(j\) 维肯定是取到 \(v_j\)
我们再将上面那个变一下,令
显然 \(g_{i,*}\) 与 \(g_{i,*}'\) 是等价的,所以发现这个时候我们就能将 \(V\) 限制为 \(\le \min{pre_i,suf_{i+1}}\) 了
不过转移的时候每一维都要取 \(\max\) 很麻烦,考虑记 \(f_{i,V}=\sum\limits_{V1 \le V} g_{i,V1}\) ,这样转移就变成了对于 \(V \ge V_i\) 的, \(f_{i,V} \leftarrow f_{i-1,V} \times (a[i]+1)\)
我们维护一个这样的算法
首先我们记一个范围 \(LIM\) 表示我们只维护 \(f_{i,V} \quad (V \le LIM)\) ,每次准备转移 \(i\) 时进行如下三步
将 \(LIM\) 变为 \(\min(pre_i,suf_i)\) ,那么有 \(f_{i,V}'=f_{i,\min(V,LIM)}\) (这是原本的 \(LIM\) )
然后转移 \(f\)
最后通过上面那个性质将 \(f\) 限制到 \(\forall V \not \le suf_{i+1},f_V=0\) ,并将 \(LIM\) 变为 \(\min(pre_i,suf_{i+1})\)
第一步时 \(LIM=\min(pre_{i-1},suf_{i}) \le \min(pre_i,suf_i)\) ,所以不会丢失信息
考虑将 \(f\) 进行限制到底是个怎样的过程,先只观察其中一维 \(j\) 满足 \(v_j=LIM_{j}\) ,记 \(V'_{k}\) 即是 \(V\) 在第 \(j\) 维减 \(k\) 的向量,那么一次上面的变换有(这里 \(f\) 可能用混淆了,不过应该能区分函数与数组)
那么一直推下去可以得到
可以发现算法的三步中都能直接暴力枚举并压缩转移前和转移后的状态,记 \(L_i=\min(pre_i,suf_i)\) ,则一次转移的复杂度为 \(O(\prod\limits_{j=1}^{k} (L_{i,j}+1))\)
计算一下这个之和,论文中也有这个表,可以发现大到爆炸,但是如果我们先以 \(Max_j=\max\limits_{i=1}^n v_{i,j}\) 将 \(k\) 维排个序,然后以此再让 \(V_i\) 按字典序从小到大排序,一下就能跑 \(2000\) 了,只能说很牛逼