AtCoder Beginner Contest 150
AtCoder Beginner Contest 150(ABC150)に参加しました!
解けた問題だけ解説をしていきますー
要項
AtCoder Beginner Contest 150
rated ~1999
2020/1/10(金) 21:00 ~ 22:40 (100分)
100-200-300-400-500-600 (6問)
ペナルティ: 5分
方針
全完
A - 500 Yen Coins
問題文
高橋君は円玉を枚持っています。これらの総額が円以上である場合は
Yes
を、そうでない場合はNo
を出力してください。制約
解法
持っているお金は円なので、これが以上か判定すれば良いです。
感想
最初の問題なので、やるだけです。
B - Fusing Slimes
問題文
英大文字のみからなる長さの文字列があります。
の連続する部分列としてABC
がいくつ含まれるかを求めてください。制約
- は英大文字からなる。
解法
殆どの標準ライブラリには、部分文字列を取り出す関数や文字列の比較を行う関数が備わっています。
例えばJavaの場合、String.substring(i - 2, i + 1);でi-2文字目からi文字目までの文字列を切り出すことができ、String.equals("ABC")でその文字列がABC
と一致するか比較することができます。
従って、後はこの開始点iをからまで動かせば良く、これはfor文などで実現できます。
感想
標準ライブラリを知っておくと便利なことが多いので、調べて損は無いと思います。
そもそもそのライブラリが標準に入っている理由は、需要が高かったからなのですから。
C - Count Order
問題文
大きさの順列 (を並び替えてできる数列)があります。
大きさの順列は通り考えられます。このうち、が辞書順で番目に小さく、が辞書順で番目に小さいとして、を求めてください。注記
つの数列について、ある整数が存在してかつが成り立つとき、はより辞書順で小さいと定義されます。制約
- は大きさの順列である。
- 入力は全て整数である。
解法
nextPermutationというアルゴリズムが存在します。
詳しくは調べていただけると分かるのですが、ある列の辞書順で次の列を求め、また辞書順で次の列が存在するか判定してくれるアルゴリズムです。
これを用いると、それぞれの順列が辞書順で最も大きい順列から何個離れているかを求めることができるので、後は差を取ると判定できます。
D - Semi Common Multiple
問題文
長さの偶数からなる正の整数列と、整数が与えられます。
任意のに対して以下の条件を満たす正の整数をの「半公倍数」と定義します。
- を満たす負でない整数が存在する。
以上以下の整数のうちのの半公倍数の個数を求めてください。
制約
- は偶数である。
- 入力は全て整数である。
解法
制約よりは偶数なので、と定義します。
この時、と変形され、問題は全て整数で表すことができます。
この時、と表せることから、は任意のの倍数である、すなわちの公倍数であることが分かります。
の最小公倍数をとすると、は整数を用いてと表すことができます。
また、より、は奇数である必要があります。
ここでが偶数であるならば任意の正の整数を掛けても偶数なので、条件を満たすは存在しません。
逆に任意のについてが奇数であるならばが奇数の時に条件を満たします。
従って、を満たすような整数が答えとなり、これは式変形すれば求まります。
を求める際、最小公倍数がオーバーフローする可能性には気を付けましょう。
例えば実装の工夫として、最小公倍数を求める場合には2項の最小公倍数の公式を用いてと解くと思いますが、この際の各は高々2乗に収まる、すなわち程度に収まることを利用して、もしならばとするとオーバーフローを防げます。
感想
重いし罠があるし400点問題としては難しい分類の問題です。
ついでに言うとテストケースも誤っているし、正直言って辛いね……。
E - Change a Little Bit
問題文
からなる長さの異なるつの数列に対し、関数を以下のように定めます。
- に対し以下の操作を繰り返してと等しくすることを考える。このとき行う操作のコストの和として考えられる最小の値がである。
- を (から、もしくはからに) 変更する。この操作のコストは、変更の直前にであったような整数の個数をとして、である。
からなる長さの異なるつの数列の組は通り考えられます。これらすべてに対するの和をで割った余りを計算してください。
制約
- 入力は全て整数である
解法
まず、同じ数列の組が存在したとしても答えに影響はしない(そのような数列のコストはである)ので、同じ数列の組を許容します。
また、数列とし、数列の番目の項をとの値が異なるなら、そうでないならと定めた新しい数列を考えると、元の数列から新しい数列へは一対一に対応するので、元の問題の代わりに数列について解いても一般性を失いません。
この時、数列は常にであることから、ある数列に対応する数列は全部で個あることが分かります。
従って、各数列について解き、その答えを最終的に倍すると元の問題の答えになることが分かります。
さて、ある数列についてある数列が存在してがであり、このの順に操作するとします。
この時のコストはであることから、の順番はの大きい順にすることが最適であることが分かります。
よって、まずを降順ソートしておくものとします。
次に、について各が何回コストとして数えられるかを考えます。
まずがであるような組合せは明らかに通りあります。
また、がであり、かつがであるような組合せ(先にを取るためにが複数回数えられる)は各について通りあります。
従って、各については通りあることが分かるので、最終的なコストはです。
感想
期待値の線形性など、何が独立に数え上げられるかを知っていると割と自明に見える問題だと思います。
この手の言い換えは高校数学でも頻出なので、もし良ければ数Aなどを勉強してみると良いのかもしれません。
F - Xor Shift
問題文
非負整数からなる長さの数列とが与えられます。
すぬけ君はを満たす整数と、以上の整数を決めて、新しく長さの数列を次のようにして作ります。
がと等しくなるようなの組を全て求めてください。
制約
- 入力中のすべての値は整数である。
解法
解けませんでした。
結果
ooooo- 5完(1500点) 17:10-18:43-14:19-30:50(1WA)-46:07-xx:xx / 51:00
106位 パフォーマンス: 2250
感想
F問題、かなり難しい……。
文字列アルゴリズムも整備するべきなのかなぁ。