AtCoder Beginner Contest 234のきろく
またまた日が空きました。AtCoder Beginner Contest 234に参加です。
- A - Weird Function (100点)
- B - Longest Segment (200点)
- C - Happy New Year! (300点)
- D - Prefix K-th Max (400点)
- E - Arithmetic Number (500点)
- F - Reordering (500点)
- G - Divide a Sequence (600点): 未提出
- Ex - Enumerate Pairs (600点、実行時間制限: 4 sec): 未提出
- 結果、感想
A - Weird Function (100点)
問題文にあるような関数を実装して、f(f(f(t)+t)+f(f(t)))
を出力させればいいです。
また、 であるため、こちらを実装するのもありでしょう。
多項式の計算にはHorner法を用いることで累乗による計算回数を減らすことができます。
B - Longest Segment (200点)
点の個数が と小さいため、全ての組 についての線分の長さ を計算して最大値を求めればいいです。
C++などの言語ではstd::fixed
, std::setprecision
や"%.8d"
などを用います。
C - Happy New Year! (300点)
を に変換してもその大小関係は変わらないため、条件を満たす中で 番目に小さい数は二進数表記での に対応します。そのため十進数を二進数に変換し、 を に変換することで答えが求まります。
D - Prefix K-th Max (400点)
毎回、既出の数のリストから 番目に大きな数を求めたり、ソートしたりすると計算量が や となってしまい、TLEします。
ある時点で大きい方から 番目以降の数がそれ以降で答えになることはないため、各時点での大きい方から 番目までの数が分かればいいです。よってこれらを集合std::set
や優先度付きキューstd::priority_queue
を用いて、毎回、この集合内の最小値と の比較で大きい方を集合内にあるようにして要素数が常に になるようにすれば、その中の最小値が各回の答えになり、全体として になります。
コンテスト内では最初は、二重二分探索で 解で通しましたが、探索範囲を間違えて2WA出してしまいました。
E - Arithmetic Number (500点)
一番左の数は から の 通り、公差は から の 通りであるため、これらを全探索することができます。各条件について右に数を増やしていき(増やす数がマイナスになればその条件については打切り)、 以上になったら、答えの候補にして、その中の最小値が答えとなります。
F - Reordering (500点)
内の 種目の英小文字の出現数を とします。このとき
というDPを考えます。公式解説では貰うDPで考えているようでしたが、私は配るDPをもとに考えました。の状態について 種目の英小文字を文字の隙間(前後含む) 個の隙間に配置していきます。このとき同じ隙間に複数個おいてもよく、1個も置かれない隙間があってもいいです。初期状態として について に を足すことで答えが と求まります。ここで は重複組み合わせで であり、変形すると公式解説と同じとなります。
G - Divide a Sequence (600点): 未提出
これもDPっぽいですが、未だ解けてません。
Ex - Enumerate Pairs (600点、実行時間制限: 4 sec): 未提出
計算量が落ちない...
結果、感想
ちゃんと6完で来たので良かったという感じですが、Dで2WA出してしまったのが痛いなと、要反省です。