日记
久蹲一定要慢起,我今天差点死在厕所。
神秘小唐题。
神秘小 dp。设 dpi,x,y 表示前 i 轮取完剩下两个数是 x,y 的最大答案,使用滚动数组优化,初始化 dpa1,a2=dpa2,a1=0,其余全是 −inf。设当前的三个数是 u,v,w,考虑转移:
做出贡献:
- u=v=w
显然是贪心的取这三个数,cnt 加上 1 然后 continue
。 - u=v∨v=w∨u=w
我们把这三个数看做 {a,a,b},有两种方式可以做出贡献:{b,b∣a,a,b},{a,c∣a,a,b}。前者可以 O(1) 转移:dpa,a←dpb,b+1。后者可以枚举 c 做到 O(n) 转移:dpb,c←dpa,c+1。 - otherwised.
有三种方式可以做出贡献:{u,d∣u,v,w},{v,v∣u,v,w},{w,w∣u,v,w},分别表现为 dpv,w←dpu,d+1,dpu,w←dpv,v+1,dpu,v←dpw,w+1。
不做出贡献:
- 扔掉 u,v,w
剩下的两个数没变,由于是滚动数组,所以不操作。 - 扔掉 u,v,w 的其中两个
我们可以枚举 c,d 来从 dpc,d 来转移到 dpc,d/v/w,但是转移的显然是 maxd=1ndpc,d,所以我们可以通过维护 maxcc=maxd=1ndpc,d 来转移。 - 扔掉 u,v,w 其中一个:
依然是枚举 c,d,从 dpc,d 转移。我们可以记录一个 ans 表示整个 dp 数组的最大值。
还有一个小妙招:由于转移的时候要同时更新 ans 和 maxc,所以对于 dpx,y←z,可以通过一个 vector<array<int,3>>
来记录 {x,y,z},之后一起转移,复杂度 O(n2)。
设 dpl,r,d 表示在左边界为 l,右边界为 r,下边界为 d 的时候的最小(就是最上)的上边界在哪里。显然有 ans=maxl=1mmaxr=1mmaxd=1n(r−l+1)×(d−dpl,r,d)。
考虑如何转移。我们发现一个 [l,r] 区间非法,当且仅当 [l+1,r] 非法或者 [l,r−1] 非法或者 l,r 这两列合起来非法。那么转移有 dpl,r,d=max(dpl+1,r,d,dpl,r−1,d,fl,r,d)。其中 fl,r,d 表示在下边界为 d 时只看 l,r 两列能延伸到哪,复杂度 O(n3)。
没改。
我们直接开始推柿子:
ans=i=1∑nj=1∑ngcd(i,j)k=2i=1∑nj=1∑igcd(i,j)k−i=1∑ngcd(i,i)k=2d=1∑ndki=1∑⌊dn⌋j=1∑i[gcd(i,j)=1]−i=1∑nik=2d=1∑ndki=1∑⌊dn⌋φ(i)−i=1∑nik设 sum(n,k)=∑i=0nik,我们有神秘小公式:sumn,k=k+1(n+1)k+1−∑j=0k−1(jk+1)sum(n,j),可以在 O(k2) 的复杂度内求出 ∑i=1nik,对于 k≤5 完全够用。然后我们就可以数论分块了 + 杜教筛了,时间复杂度 O(能过)。
为啥你不会骗分?