[loj2087][NOI2016]国王饮水记

11 篇文章 0 订阅
1 篇文章 0 订阅

前言

回归OI,随便找一道清真dp题写写吧
做完发现一点都不清真

题目相关

链接

题目大意

现在有 n n n个数,每次可以取若干个数,将每个数赋成平均值,限制 k k k次,问第一个数最大能变成多少

数据范围

n ≤ 1000 , k ≤ 1 0 9 n\le1000,k\le10^9 n1000,k109
另外,精度要求 p p p位, 3 ≤ p ≤ 3000 3\le p\le3000 3p3000

题解

n n n个数为 h 1 , h 2 , h 3 ⋅ ⋅ ⋅ h n h_1,h_2,h_3···h_n h1,h2,h3hn

  • 对于 ∀ i ∈ [ 2 , n ] \forall i\in[2,n] i[2,n]满足 h i ≤ h 1 h_i\le h_1 hih1,这个数肯定不会被使用

这个很好证明, h i h_i hi与大于 h 1 h_1 h1的数取平均只会让那些数变小,不优, h i h_i hi与小于等于 h 1 h_1 h1的数取平均不会让他们变得大于 h 1 h_1 h1

  • 每次取平均一定是包含 h 1 h_1 h1

由于上一条我们已知,取平均的一定比 h 1 h_1 h1大,那就有
h 1 + h 2 + h 3 2 2 &lt; h 1 + h 2 + h 3 3 \frac{h_1+\frac{h_2+h_3}2}2&lt;\frac{h_1+h_2+h_3}3 2h1+2h2+h3<3h1+h2+h3
(因为 h 1 &lt; h 2 , h 1 &lt; h 3 h_1&lt;h_2,h_1&lt;h_3 h1<h2,h1<h3

  • 使用完一个数后,这个数将不会再被使用

根据取平均的性质,再根据第一条可得

  • 如果次数足够多,那一定是从小到大一个个一次与 h 1 h_1 h1取平均的

h 1 + h 2 2 + h 3 2 &gt; h 1 + h 2 + h 3 3 \frac{\frac{h_1+h_2}2+h_3}2&gt;\frac{h_1+h_2+h_3}3 22h1+h2+h3>3h1+h2+h3
h 1 &lt; h 2 &lt; h 3 h_1&lt;h_2&lt;h_3 h1<h2<h3
所以大于 n n n k k k都是没用的,下文的 k k k的数据范围均可当作小于等于 n n n

然后就是次数不够多的情况,我们发现有些要合并
考虑dp
f i , j f_{i,j} fi,j表示用了前 i i i个数,进行了 j j j次取合并的最大值
f i , j = m a x { m a x { ( f k , j − 1 + ∑ l = k + 1 i h l ) / ( i − k + 1 ) } , f i − 1 , j } f_{i,j}=max\{max\{(f_{k,j-1}+\sum_{l=k+1}^ih_l)/(i-k+1)\},f_{i-1,j}\} fi,j=max{max{(fk,j1+l=k+1ihl)/(ik+1)},fi1,j}
不能忘记与 f i − 1 , j f_{i-1,j} fi1,j取max,因为在次数不够的时候,并不一定所有数都要取
此处复杂度为 O ( n 2 k p ) \mathcal O(n^2kp) O(n2kp)的,显然不能通过
∑ \sum 改成前缀和相减的形式
s i = ∑ j = 1 i h j s_i=\sum_{j=1}^ih_j si=j=1ihj
f i , j = m a x { m a x { ( f k , j − 1 + s i − s k ) / ( i − k + 1 ) } , f i − 1 , j } f_{i,j}=max\{max\{(f_{k,j-1}+s_i-s_k)/(i-k+1)\},f_{i-1,j}\} fi,j=max{max{(fk,j1+sisk)/(ik+1)},fi1,j}
把j这一维提掉
n e w f i = m a x { m a x { ( f k + s i − s k ) / ( i − k + 1 ) } , n e w f i − 1 } newf_i=max\{max\{(f_k+s_i-s_k)/(i-k+1)\},newf_{i-1}\} newfi=max{max{(fk+sisk)/(ik+1)},newfi1}
调整
n e w f i = m a x { m a x { ( s i − ( s k − f k ) ) / ( i − ( k − 1 ) ) } , n e w f i − 1 } newf_i=max\{max\{(s_i-(s_k-f_k))/(i-(k-1))\},newf_{i-1}\} newfi=max{max{(si(skfk))/(i(k1))},newfi1}
变成斜率的形式
当前点 ( i , s i ) (i,s_i) (i,si)要找一个点 ( k − 1 , s k − f k ) (k-1,s_k-f_k) (k1,skfk)使得他到我斜率最大
一个好想的方法是动态维护凸包,然后三分即可复杂度 O ( n 2 l o g n p ) \mathcal O(n^2lognp) O(n2lognp)
事实上不需要三分,我们发现,如果新的斜率比上一个劣,是可以直接max上上一个的,由于每次询问的横坐标都增加了,如果更新了答案一定是在上次的决策右边

如图如果是当前2的情况,斜率是没有上一次优的,如果是当前1的情况,决策一定是在右边
所以此处有决策单调性,不需要三分
目前复杂度为 O ( n 2 p ) \mathcal O(n^2p) O(n2p)

  • 最优答案的转移过程中的 i − k i-k ik是单调不增的

比如
x + x 1 2 + x 2 + x 3 3 &lt; x + x 1 + x 2 3 + x 3 2 \frac{\frac{x+x_1}{2}+x_2+x_3}{3}&lt;\frac{\frac{x+x_1+x_2}{3}+x_3}{2} 32x+x1+x2+x3<23x+x1+x2+x3
( x &lt; x 1 &lt; x 2 &lt; x 3 ) (x&lt;x_1&lt;x_2&lt;x_3) (x<x1<x2<x3)
一般化:
x + x 1 + ⋅ ⋅ ⋅ + x k − 1 k + x k + ⋅ ⋅ ⋅ + x n n − k + 2 &lt; x + x 1 + ⋅ ⋅ ⋅ + x k k + 1 + x k + 1 + ⋅ ⋅ ⋅ + x n n − k + 1 \frac{\frac{x+x_1+···+x_{k-1}}{k}+x_k+···+x_n}{n-k+2}&lt;\frac{\frac{x+x_1+···+x_k}{k+1}+x_{k+1}+···+x_n}{n-k+1} nk+2kx+x1++xk1+xk++xn<nk+1k+1x+x1++xk+xk+1++xn
( x &lt; x 1 &lt; x 2 &lt; x 3 ⋅ ⋅ ⋅ &lt; x n , k &lt; n − k + 1 ) (x&lt;x_1&lt;x_2&lt;x_3···&lt;x_n,k&lt;n-k+1) (x<x1<x2<x3<xn,k<nk+1)
证明:
先由条件得到 2 k ≤ n 2k\le n 2kn
全部通分
( n − k + 1 ) ( x + x 1 + ⋅ ⋅ ⋅ + x k − 1 + k ( x k + ⋅ ⋅ ⋅ + x n ) ) &lt; ( n − k + 2 ) ( x + x 1 + ⋅ ⋅ ⋅ + x k + ( k + 1 ) ( x k + 1 + ⋅ ⋅ ⋅ + x n ) ) (n-k+1)(x+x_1+···+x_{k-1}+k(x_k+···+x_n))&lt;(n-k+2)(x+x_1+···+x_k+(k+1)(x_{k+1}+···+x_n)) (nk+1)(x+x1++xk1+k(xk++xn))<(nk+2)(x+x1++xk+(k+1)(xk+1++xn))
移项(+式子美化)
0 &lt; x + ∑ i = 1 k − 1 x i + ( n − k + 2 − ( n − k + 1 ) k ) x k + ( ( n − k + 2 ) ( k + 1 ) − ( n − k + 1 ) k ) ( ∑ i = k + 1 n x i ) 0&lt;x+\sum_{i=1}^{k-1}x_i+(n-k+2-(n-k+1)k)x_k+((n-k+2)(k+1)-(n-k+1)k)\left(\sum_{i=k+1}^nx_i\right) 0<x+i=1k1xi+(nk+2(nk+1)k)xk+((nk+2)(k+1)(nk+1)k)(i=k+1nxi)
0 &lt; x + ∑ i = 1 k − 1 x i + ( n − 2 k + 2 − n k + k k ) x k + ( n + 2 ) ( ∑ i = k + 1 n x i ) 0&lt;x+\sum_{i=1}^{k-1}x_i+(n-2k+2-nk+kk)x_k+(n+2)\left(\sum_{i=k+1}^nx_i\right) 0<x+i=1k1xi+(n2k+2nk+kk)xk+(n+2)(i=k+1nxi)
x + ∑ i = 1 k − 1 x i + ( n − 2 k + 2 − n k + k k ) x k + ( n + 2 ) ( ∑ i = k + 1 n x i ) &gt; x + ∑ i = 1 k − 1 x i + ( n − 2 k + 2 − n k + k k ) x k + ( n + 2 ) ( n − k ) x k x+\sum_{i=1}^{k-1}x_i+(n-2k+2-nk+kk)x_k+(n+2)\left(\sum_{i=k+1}^nx_i\right)&gt;x+\sum_{i=1}^{k-1}x_i+(n-2k+2-nk+kk)x_k+(n+2)(n-k)x_k x+i=1k1xi+(n2k+2nk+kk)xk+(n+2)(i=k+1nxi)>x+i=1k1xi+(n2k+2nk+kk)xk+(n+2)(nk)xk
······根据 x k &lt; x k + 1 &lt; ⋅ ⋅ ⋅ &lt; x n x_k&lt;x_{k+1}&lt;···&lt;x_n xk<xk+1<<xn
x + ∑ i = 1 k − 1 x i + ( n − 2 k + 2 − n k + k k ) x k + ( n + 2 ) ( n − k ) x k &gt; ( n − 2 k + 2 − n k + k k ) x k + ( n + 2 ) ( n − k ) x k x+\sum_{i=1}^{k-1}x_i+(n-2k+2-nk+kk)x_k+(n+2)(n-k)x_k&gt;(n-2k+2-nk+kk)x_k+(n+2)(n-k)x_k x+i=1k1xi+(n2k+2nk+kk)xk+(n+2)(nk)xk>(n2k+2nk+kk)xk+(n+2)(nk)xk
·····根据 x &gt; 0 x&gt;0 x>0减去一些正数会变小
( n − 2 k + 2 − n k + k k ) x k + ( n + 2 ) ( n − k ) x k = ( n n − 2 k + 2 n − n k + n − 2 k + 2 − n k + k k ) x k = ( n ( n − k ) − k ( n − k ) + 2 n − 4 k + n + 2 ) &gt; 0 (n-2k+2-nk+kk)x_k+(n+2)(n-k)x_k=(nn-2k+2n-nk+n-2k+2-nk+kk)x_k=(n(n-k)-k(n-k)+2n-4k+n+2)&gt;0 (n2k+2nk+kk)xk+(n+2)(nk)xk=(nn2k+2nnk+n2k+2nk+kk)xk=(n(nk)k(nk)+2n4k+n+2)>0
······根据 2 k ≤ n , n &gt; 0 2k\le n,n&gt;0 2kn,n>0可得
至此证毕

  • 最优答案的转移过程中 i − k &gt; 1 i-k&gt;1 ik>1的段数仅有 O ( l o g n h Δ ) \mathcal O(log\frac{nh}{\Delta}) O(logΔnh)个, Δ = m i n i { h i − h i − 1 } \Delta=min_i\{h_i-h_{i-1}\} Δ=mini{hihi1}
    这个地方看了讲稿也不懂了(看了很久都没弄懂
    在这里插入图片描述
    在这里插入图片描述
    贴个讲稿的link
    这样就只转移14次
    此处有会证明的教教我啊
    最后复杂度的话就是 O ( n p l o g n h Δ ) \mathcal O(nplog\frac{nh}{\Delta}) O(nplogΔnh)

代码

然后还要使用高精小数板子

代码先鸽一会儿,很快就来

总结

体验好差233

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值