Codeforces Round #565 (Div. 3) Problem D. Recover it!
問題概要
長さ の数列 に対して, 以下の操作によって数列 を得る.
例えば, のとき, は順にであるから, としてたとえば などが得られるわけです. ( は 番目の素数, は 番目の素数であることに注意します).
問題では があたえられるので, を復元してください.
制約
- ( は 番目の素数)
- 元の数列 の要素は 以上 以下
解法
上手にマッチングしてくださいという問題です. 少し考えるとわかることですが, が素数のとき, 追加される要素 は必ず よりも大きくなり, 逆に が非素数のとき は よりも小さくなります.
そこで, まず を降順にソートし, が大きい順にみていくことにすれば,
- が素数 → が 元の数列 に属しているとすると, よりも大きな素数 が手順2で追加されていることになります. これは大きい順にみていることに矛盾するため, は に属さない要素です.
- が非素数 → が 元の数列 に属していないとすると, を他の数から生成しなければなりませんが, これは が一番大きいという事実に矛盾します.
ということで, 次のようなアルゴリズムを考えれば良いです.
- を降順にソートする.
- を大きい順にみていき, もし が素数なら に対応する素数 ( 番目の素数が となるような )を答えの数列に追加し, を から削除する. が非素数なら, を答えの数列に追加し, の最大の約数 を から削除する.
- 答えを出力する.
計算量についてですが, 素数の列挙はエラトステネスの篩で実装すればいいです. 問題は 2.の が非素数の場合に最大の約数を見つけてくるところですが, 普通に から割れるか試していき最初に割り切れる数 をみつけてきて とすればよいです. これは 程度の時間がかかりますが, 毎回試しても大丈夫です. 実行時間 秒もあるので.