前言
太笨了,不会拆贡献,所以复杂度比较劣。
题意
给定操作 A 和操作 B。
定义操作 A 是将 xi←xi−1(xi>0) 并获得 ∑xik 分数,xi 是第 i 个怪物扣血前的血量,k 是总操作 B 次数。如果一次操作后会有新的 xi=0,则继续进行操作 A。
定义操作 B 是当此时没有新的 xi=0,进行一次操作 A。
给定集合 S={x∈[1,n]∧x∈/a} 表示怪物血量所构成的集合,求最后的总分数。
做法
k 是好算的。
将 S 拆成一段段连续的区间分别考虑,一段连续的区间必定是在同一次操作 B 中扣为 0。
设当前处理的血量区间为 [li,ri],对于 j≥i 的区间当前血量为 [lj,rj],则当前的贡献 ∑j=im+1∑x=ljrj∑y=x−li+1xyk。
直接计算是 O(Tm2n2),这里放一份代码。
思考如何优化计算 ∑x=ljrj∑y=x−li+1xyk,设 f(x)=∑i=1xix,g(x,len)=∑i=1x(f(i)−f(i−len)),则 ans=∑i=1m+1∑j=im+1g(rj,li)−g(lj−1,li)。
可以先使用一次拉格朗日插值 O(m) 算出 f(x),进而再使用一次拉格朗日插值 O(m2) 算出 g(x)。
总时间复杂度为 O(T×m4),需要轻微卡常。
AC Code