G - Infinite Knapsack Editorial by Rssll_Krkgrd


双対を取るところまではpotato167さんの解説と同じです。
ここで、\(y\geq0\)を固定すると、

  • \(\forall i \space C_i\leq yA_i+zB_i\)
  • \(z\geq0\)

を満たす\(z\)の範囲は\(\begin{aligned}z\geq\max\left\{\max_i\left\{\frac{C_i-yA_i}{B_i}\right\},0\right\}\end{aligned}\)となるため、このときの\(y+z\)の最小値は\(\begin{aligned}y+\max\left\{\max_i\left\{\frac{C_i-yA_i}{B_i}\right\},0\right\}\end{aligned}\)となります。
これを\(f(y)\)とおきます。
すると、凸関数の\(\max\)が凸関数になることを考えると、\(f(y)\)は凸関数となります(\((y,z)\)の組がとりうる値の範囲をグラフに書くとより直感的に理解できると思います)。
したがって、三分探索により\(f(y)\)の最小値を求めればこの問題を解くことができます。
また、\(\begin{aligned}y\geq\max_i\left\{\frac{C_i}{A_i}\right\}\end{aligned}\)の範囲では\(f(y)=y\)となるため、三分探索の上限は\(\begin{aligned}\max_i\left\{\frac{C_i}{A_i}\right\}\end{aligned}\)とすればよいです。
実装例(Python)

posted:
last update: