エクサウィザーズ 2019 D - Modulo Operations
解法
(現在黒板に書かれている数字に影響があるような数字を取り除くことをここでは”使う”、ないような数字を取り除くことを”使わない”と表現します)
まず、回目に取り除いた数字よりも大きい数字を、回目以降で取り除いても、黒板に書かれる数字に影響はありません。
ということで、を降順にソートしておくと、前から見ていき、使うか使わないかの選択をするだけで、最終的に黒板に書かれる数字が決まります。
これを踏まえたうえで、次のようなDPをします。
番目までの要素について使う、使わないを決めた上で、黒板に書かれている数字がになるような並べ方の場合の数
ここでの並べ方、というのは少し特殊で、 ~ をただ並べる、というものではなく、長さの数列に ~ を配置する方法、とします。
初期値は、となります。
このDPが計算できると、答えは (ただし )となります。
番目の要素を"使わない"場合
番目の要素は、長さの数列でまだ埋まっていない箇所のうち、左端以外に配置することで、この条件を満たすことができます。配置できる場所は全部で個です。
この場合、黒板に書かれている数字はもちろん番目までを配置し終えた状態から変化しないので、このパターンの場合の数は
となります。番目の要素を"使う"場合
まず、の場合は明らかに0です。を取り除いた時点で、黒板の数字はそれより小さくなっているはずです。
番目の要素は、長さの数列のまだ埋まってない箇所のうち、一番左に配置することで、この条件を満たします。配置できるのはこの1通りのみです。
また、は、番目の要素を使うことで黒板の数字がになります。
よって、このパターンの場合の数は
(ただし )
となります。
あとは、上の2つのパターンの和を取ればよいので、( の時)
( の時 )
という計算をすればよいです。
このDPを計算できたら、最後に
(ただし )
を出力して終了となります。
DPの遷移の中で、総和をとっていく部分によって計算量が大きくなりそうに見えますが、実は時間内に間に合います。 総和のループが回る最悪ケースは、のときで回ですが、この総和を計算するケースはという条件が必要なため、たかだか回です。つまり、少なくとも回には収まっています。
感想
小さい数字でmodを取った時点で、それより大きい数字が影響を及ぼすことはない、という考察は割とすんなりでてきました。
DPをするときに一部のみを見るだけでよい(今回で言うとある値で割った余りをDPの添え字にする)、というのは、LCMラッシュが似たような考え方をしているので、この問題を解いていてよかったです(思いつくのには時間がかかりましたが)。