sankantsuのブログ

技術メモ・競プロなど

ABC251 D - At Most 3 (Contestant ver.) 解説

atcoder.jp

数列をうまくつくることで,数列から3個以下の数を選んでW以下の任意の数をつくれるようにせよという問題

 Wが最大値10^ 6であるときに解となる数列さえ求めれば,この数列を使って10^ 6以下の任意の数がつくれるのでW \lt 10^ 6を満たす任意の Wに対する解にもなっていることがわかる. よって, W=10^ 6の場合の解を求めることに注力すれば良い.

与えられた数をいくつかの数の和に分解したいので,このために都合の良い表示を考えたい. このときに桁を分けて考えるというのが有効な考え方になる. 例えば,適当に2563という数を考えると,2563 = 2000 + 563 や,2563 = 2500 + 63 のように桁が独立している数どうしの足し算は考えやすい.

 10^ 6未満の数は10進で6桁の数として表せるので,2桁ずつに分解して各グループについて00から99まですべての数をつくれば,各グループから1つずつ数を選んで組み合わせることで6桁以下の任意の数を表現できる.(00は 0 であり,そのグループからは数を選ばないということによって表現できるので,明示的につくる必要はない)

最後に,1000000という数だけは7桁なのでこれだけ別に数列に加える. 以上で任意の数を構成できた.

実装例

github.com

備考

もちろん10進ではなく2進表示などでも原理的にはよいのだが,たとえば2進で10^ 6以下の数を表現しようとすると20桁いる. 7桁,7桁,6桁に分けて各グループについてすべての数をつくると,2^ 7 + 2^ 7 + 2^ 6 = 320程度の数が必要になるので制約を満たさない. 今回は上限が10^ 6という10進できりの良い数になっているので10進表示で考えるのが一番無駄がないということだろう.