G - Freefall 解説
by
MMNMM
別解
この問題は、単峰性のある関数 \(f(x)\) の最小値を求める問題です。 単峰性のある関数は、差分 \(f(x+\varepsilon)-f(x)\) や微分可能ならその微分 \(f^\prime(x)\) の符号が単調という性質があります。 微分や差分の符号を計算することが容易なら、それを用いて二分探索を用いることで探索回数を減らすことができます。
今回は、最小化すべき関数 \(f(x)=Bx+\dfrac{A}{\sqrt{x+1}}\) が自然数 \(\mathbb{Z}_{\geq0}\) から実数 \(\mathbb{R}\) への写像なので、差分 \(f(x)-f(x-1)\) が負であるような最大の \(x\ (\gt0)\) (存在しなければ \(0\))が \(f\) を最小にする \(x\) です。
\[\begin{aligned} f(x)-f(x-1)&=\left(Bx+\dfrac{A}{\sqrt{x+1}}\right)-\left(B(x-1)+\dfrac{A}{\sqrt x}\right)\\ &=B+A\left(\dfrac1{\sqrt{x+1}}-\dfrac1{\sqrt x}\right)\\ &=B-A\dfrac1{\sqrt{x(x+1)}\left(\sqrt x+\sqrt{x+1}\right)} \end{aligned}\]
と計算できるので、 \[\begin{aligned} f(x)-f(x-1)\lt0&\iff B-A\dfrac1{\sqrt{x(x+1)}\left(\sqrt x+\sqrt{x+1}\right)}\lt0\\ &\iff A\gt B\sqrt{x(x+1)}\left(\sqrt x+\sqrt{x+1}\right)\\ &\iff A^2\gt B^2x(x+1)\left(2x+1+2\sqrt{x(x+1)}\right)\\ &\iff A^2-B^2x(x+1)(2x+1)\gt2B^2x(x+1)\sqrt{x(x+1)}\\ &\iff A^2\gt B^2x(x+1)(2x+1)\wedge A^4 +B^4x^2(x+1)^2\gt 2A^2B^2x(x+1)(2x+1) \end{aligned}\] となります。これは整数どうしの演算で判定できるので、二分探索でこの問題が解けました。
二分探索を行うとき、はじめの区間は \(\left\lbrack 0,\left\lceil\dfrac AB\right\rceil\right\rparen\) とするとよく、反復回数は \(\max\left\{\lceil\log_2A-\log_2B\rceil,0\right\}\) 回で十分高速です。
答えの計算をする際に浮動小数点数で計算を行うことになりますが、平方根の計算や四則演算は正確な結果を丸めたものが得られるため、たとえば倍精度浮動小数点数などを用いて計算すると相対誤差はたかだか \(6.7\times10^{-16}\) 程度と評価でき、十分正確です。
実装例は以下のようになります。 判定には最大で \(10^{54}\) 程度の大きさの整数の演算が必要になる場合があることに注意してください。
from math import sqrt
A, B = map(int, input().split())
L, R = 0, (A + B - 1) // B
while L + 1 < R:
M = (L + R) // 2
condition_0 = A * A > B * B * M * (M + 1) * (2 * M + 1)
condition_1 = A ** 4 + B ** 4 * M * M * (M + 1) * (M + 1) > 2 * A * A * B * B * M * (M + 1) * (2 * M + 1)
if condition_0 and condition_1:
L = M
else:
R = M
print(A / sqrt(L + 1) + B * L)
投稿日時:
最終更新: