CF985D Sand Fortress题解

· · 题解

不用二分,数学方法搞定

博客qwq

这道题用不上二分答案,并且需要贪心的思想。这篇题解使用贪心+数学解法,同时简单陈述二分答案的合理性。

(蒟蒻的题解,如果有疑问或者问题请指出,希望比较严谨和易懂)

看到这道题,整理一下:

接下来算 $h_1$。前面的分析过后,我们直接让等差数列的和尽可能大,剩下的尽可能小。不等式: $$ \frac{h_1(h_1+1)}{2}\leq n $$ $$ h_1^2+h_1-2n\leq0 $$ 来个图 ![](https://cdn.luogu.com.cn/upload/image_hosting/ewxtrpr9.png?x-oss-process=image/resize,m_lfit,h_340,w_450) $$ h_{1max}=\frac{-1+\sqrt{8n+1}}{2} $$ 这样已经完成了一半。**但别忘记 $h_1$ 它还有个限制:$h_1\le H$。** 于是判断一下,如果 $h_1$ 小于等于 $H$,说明 $h_1$ 取到了最大,$n$ 要么正好不剩,要么剩下的再来一个在 $[1,h_1]$ 中的数就补上了,也就是 $n$ 减一下等差数列的和,如果剩 $0$,那么 $ans$ 就是 $h_1$(项数),如果不为 $0$,那 $ans$ 就是 $h_1+1$。 如果 $h_1$ 大于 $H$ 的情况怎么办?这就说明 $h_1$ 没取到最大,就会被 $H$ 挡住,等差数列的首项是 $H$。 显然,这种情况下,我们还要额外多放几堆,这时我们的策略显然是放上面可能性的第 $3$ 种。也就是额外放置两个等差数列。设中间最高的堆为 $h_i$,我们要让 $h_1,...,h_{i-1},h_i,h_{i+1},...,h_{2i-2}$ 形成 $h_1$ 到 $h_{i-1}$ 的上升序列,和 $h_{i}$ 到 $h_{2i-2}$ 的下降序列。如图: ![](https://cdn.luogu.com.cn/upload/image_hosting/s4kkhj8f.png?x-oss-process=image/resize,m_lfit,h_340,w_450) 方程与上一个同理,两个等差数列的和为定值 $left=n-\frac{\left ( 1+H \right ) \times H}{2}$。 $$ \frac{\left ( h_1+h_{i-1} \right ) \left ( i-1 \right )}{2} +\frac{\left ( h_{i}+h_{2i-2} \right ) \left ( i-1 \right )}{2} \le left $$ $$ \frac{\left ( H+h_{i-1} \right ) \left ( i-1 \right )}{2} +\frac{\left ( h_{i}+H+1\right ) \left ( i-1 \right )}{2} \le left $$ $$ \left ( H+h_i \right ) \left ( i-1 \right ) \le left $$ $$ \left ( 2H+i-1 \right ) \left ( i-1 \right ) \le left $$ 解法同上。把 $i-1$ 当成一个数化简柿子。 还有细节没完,加上这些数列,我们可能还会剩下一些数才能凑齐 $n$。 还是用 n 减一下已经算出来的和,如果剩 $0$ ,直接统计答案,否则: 剩余的大于所有已经选的最高点,我不得不多堆两个堆; 剩余的小于等于已经选的最高点,我只需多堆一个堆。 时间复杂度,显然的 $O\left ( 1 \right )$。至于为什么比一些二分跑的慢,大概是因为``sqrt``慢的原因罢。 ## 参考代码 ~~反正我是照着草稿纸上的柿子一点一点打的~~,建议把思路搞懂,代码就简单了。 ```cpp #include<bits/stdc++.h> #define ll long long using namespace std; ll n; long long h; ll ans; int main() { scanf("%lld%lld",&n,&h); ll p=(-1+sqrt(1+8*n))/2; if(p<=h) { if(n==p*(p+1)/2)ans=p; else ans=p+1; } else { n-=h*(h+1)/2; ll x=-h+sqrt(h*h+n); ans=h+2*x; if(n>x*x+2*h*x) { n-=x*x+2*h*x; if(n<=h+x)ans++; else ans+=2; } } cout<<ans; return 0; } ``` 这里我们浅说下**为什么二分答案的解法也正确?** 我们以算出来的 $h_1$ 和 $H$ 的大小关系探讨了两步,二分答案也是同样分了两步,只是和我们的求解方式不同。我们以求解 $h_1$ 的步骤举例。 看上面的上面那张图,定义域在 $x>0$ 的情况下,恰好一部分在 $x$ 轴下,一部分在 $x$ 轴上,找的是交点的值,符合二分答案的要求。 显然,两者在题目的数据范围下实际上效率相差不大(或者都能符合要求),如果出现在比赛或者测试当中,应优先写二分的方法(不易出错),数学方法用来拓宽思路较好。