AtCoder Grand Contest 007_B_Construct Sequences
青色の問題.久々にアルゴリズムもへったくれもない問題です.数学好きなのでこういった問題の方が好きです.
問題の説明
からを並べた順列が与えられる.以下の条件を満たす数列および,を出力せよ.
条件
- 正整数列は狭義単調増加
- 正整数列は狭義単調減少
- は狭義単調増加
考えた事
問題文にある通り,答え方としてはに合わせてを作りだし,答えればよい.
まず考えるべきは全探索である.極端な話であるが*1,この問題の入力としてあり得る数列全てに合わせとを先に全て作りだせば答えとなる.
この指針には2つ問題がある.まず第一に計算量である.当然のことながら,上の方法を行う場合,計算量はとなりどう考えても無理がある.
次に解法としての適当さである.そもそもこの問題は答えをつ列挙する問題である.裏を返せば全部試すなと読めるのではなかろうか.答えが複数種類ある事を暗に示唆されている問題で愚鈍に全て試すのは明らかに効率がよくない.
ではどうすべきか.こういった問題において効果的なのは条件を徐々に厳しくする形で問題を見つめる事である.全ての条件を一気に考えても分からなくなってにゃにゃ!?となっておしまいである.我々は人間だ.カワイイカワイイにゃんこと違って物事を整理して考えねばいけない種族だ.がんばろう.
この場合だと「は狭義単調増加」はめんどうそうである.ひとまず置いて置こう.他から考える.とはいえ他の条件は狭義単調増加,狭義単調減少な数列を作るだけなのですぐできるだろう.なぜわざわざすぐできる事を分けて先に書いたか.ここが今回の大きなポイントである.
つまり今回の問題はによらず,先にの数列を作っておき,に合わせてそれを微調整するように考えればいいのである.
がどの順で大きくなるかはが入力されるまで分からない.ならば先にどんな数列を作っておくとよいだろうか.自分なら先に作っておくべき数列はによらずが同じ大きさになる数列と考える.
そして後からの順にそれぞれの数列の項にずつしていけば「は狭義単調増加」の条件も満たす.ここで注意しなければならないのは,による変化量である.これを行うと一番小さいととでの差が出来る.「は狭義単調増加」という条件を満たしたままこれを行うには,先にととでの差をつけておけばいい.
つまり,といった具合だ.そしてこれによって先に作るべきの詳細も分かる.「によらずが同じ大きさになる数列」を作ればいいのだからとなるように作ればいい.
このようにして作ったとが以上である.これによって「は狭義単調増加」以外の全てを満たし,「によらずが同じ大きさになる数列」を作成できた.
後は,
として,の順にずつ差をつけていけば,元々の条件を満たしながら「は狭義単調増加」の条件をみたす.
そしてこれは高々,であり,の制約を満たしている.以上をもって数列を作成する事に成功した.
こういった問題は典型解がなく,難しいが非常に楽しいものである.コツというか自分の考えとしては条件を緩める,特にのような変数絡みの条件を後回しにすると,解放のアプローチが得やすいだろう.ここまでお読みいただきありがとうございました.
プログラム
*1:極端とつけている時点で察しはつくかもしれない