Typical DP Contest H - ナップザック
解法
基本的な考え方は普段のナップサックと同じで、ある重さになるような荷物の選び方の中での価値の最大値、を求めていきます。
今回、荷物には色が塗られており、種類以下でナップサックに荷物をつめなければなりません。
ということで、次のようなDPを考えます。
色を種類使用して、重さの合計がになるような荷物の選び方の中での価値の総和の最大値
ここで、が何を表しているかというと、は次に見る荷物の色をまでの荷物を調べた段階で使用しているかどうか、そしてはの荷物をすでに使用したかどうか、です。
が存在することで、全ての荷物を色の番号順でソートしておけば、同じ色を違う種類と判定することなく調べることができ、が存在することで、荷物を2つ以上いれる心配がなくなります。
ということで、あらかじめ全ての荷物を、色の番号が若い順にソートしておきます。
さて、荷物に注目ときのDPの遷移を考えていきます。
まず、DPテーブルの整理から始めます。というのも、番目の荷物を調べる時も、番目の荷物を調べる時も、同じDPテーブルを再利用するためです。
2つのパターンが存在します。荷物の色が、それ以前に登場しているかどうか、です。あらかじめソートをしているので、1つ前の荷物の色と比較して、違ったならば色は番目で初出、等しければそれ以前ですでに使用していることになります。
が番目で初出ではない場合
番目の荷物について調べた際の、、すなわち番目の荷物を使用しているかどうか、という情報はもう必要ないので、にまとめ上げます。ということで、
という処理と、
という操作をしてあげます。が番目で初出だった場合
上の操作に加えて、のリセットも必要になります。番目までの荷物の組み合わせで、色の荷物を使用することがないからです。
です。それ以外は0で初期化するので、
という処理をしてあげます。
さて、DPテーブルの整理が終わったので、番目の荷物について考えていきます。
番目の荷物を使用しておらず、かつ
それまでで色の荷物を使用していなければ、色の種類数に+1
色の荷物を使用していれば、色の種類数はそのまま
となるので、DPの遷移は次のようになります。を使用した時点で、はどちらも1になることに注意します。
ということで、この更新を行いつつ、の更新を行うごとに、全体での最大値を更新していけば、この遷移が終えた段階で、更新した最大値が答えとなります。
Typical DP Contest F - 準急
解法
駅で止まるような駅までのパターン数、のようにしていきたいところですが、連続して何駅止まったか、という情報が必要になるので無理です。
逆転の発想をして、駅を通過するような駅~のパターン数、としましょう。
ダミーの駅というものが存在し、ここを必ず通過している、と仮定します。初期状態では、、そしてです。
駅で通過するには、駅を通過している、駅にはとまるが駅で通過している、駅と駅にはとまるが駅で通過している…駅から駅にはとまるが駅で通過している、というパターンがあります。
結局はこのようになります。
これは、累積和なりを用いることで、簡単に計算することができます。
あとは、答えを求めるだけです。
駅にはとまらなければならないので、駅を通過している、駅を通過してそれ以降とまる、駅を通過してそれ以降とまる、…駅を通過してそれ以降とまる、というパターンの総和になります。ここで、駅はとまる必要があるので、先ほどと条件が少しことなることに注意してください。
ということで、答えは以下のようになります。
あとは、で割った余りをとることに注意しつつ計算していけばよいです。
Typical DP Contest E - 数
解法
制約をみてもわかるように桁DPです。
とします。は、上から桁目を決める段階、という意味です。は、今作成している数字の桁和をで割った余りがであるという意味です。は、今作成している数字が未満であることが確定しているかどうか、を表します(している場合は1、なければ0です)。初期状態は、です。
の桁数を、の上から桁目をと表記することにします。
最終的な答えは、です。-1は、0を表しています。今回は正整数が条件なので、0を省かなければなりません。
桁目まで決めた段階での桁和をで割った余りがのとき、桁目をにすることを考えます(はもちろん0以上9以下です)。
これは、とについてを考えることになります。
ここから先は、との関係によって3つに場合分けされます。順番に見ていきます。
のとき
桁目を決める時点で未満であることが確定しているかどうかにかかわらず、桁目以降でどんな数字を当てはめても未満になります。ので、になります。
ということで、遷移は
となります。のとき
未満が確定しているかどうかは、桁目の時点で未満であることが確定しているかどうかに依存します。桁目の状態をそのまま受け継ぎます。
ということで、遷移は
となります。のとき
未満であることが桁目の時点で決まっていればいいですが、そうでない場合は、桁目でを選ぶとを超えてしまうので、問題の条件を満たさなくなります。ということで、についてのみ考えればよく、遷移は
のみとなります。
あとは、これを繰り返してDPを行っていけばよいです。で割った余りを求めることに注意しましょう。
Typical DP Contest D - サイコロ
問題
提出コード
復習問題だったのですが、見事MLEを吐きました。
解法
を素因数分解したときに登場する2の個数、とします(3,5も同様です)。
基本的な方針としては、
回サイコロを振ったときに、2が回、3が回、5が回登場するような確率
とします。4は2が2回分、6は2と3が1回ずつ分として計算します。
初期状態は、です。
回目に、1~6のどれを出すか、で遷移を行っていきます。
1から順番に、それぞれ以下のようになります。
答えは、を素因数分解したときに2,3,5以外の素因数が含まれていたら0、そうでなければとなるを選んだ時のの総和です。 ただし、このままだと途中でMLEやらなんやらを吐きACすることができません(少なくとも自分はそうでした)。そこで、回目でがそれぞれにたどり着いた時点で、それ以降は1~6のどの目がでても問題の条件を満たす、ということに着目すると、以下のようにDPを組み替えることができます。
このように組み替えることで、メモリを抑えつつ、また、答えはを見るだけでわかるようになります。
Typical DP Contest C - トーナメント
解法
はじめに、番の人が番の人に勝つ確率、としておきます。
番目の人が、第ラウンドで勝つ確率、とします。
初期状態はであり、答えはをすべて見ればよいです。
簡単に言えば、番目の人が第ラウンドで戦う可能性のある相手の集合をとしたときに、
となります。
さて、ここからはが0-indexedであると仮定して話を進めたいと思います(その方が好都合だからです)。
に含まれる人を探していきます。第ラウンドで番の人が対戦する可能性のある人は、全部で人います。そして、その人達の番号はすべて連番になっています。
ということで、その連番の最初がわかってしまえば、そこから人を対象として上の式による計算を行えばいいわけです。
第1ラウンドについて考えてみると、番目の人は、が奇数であれば番目の人と、が偶数であればの人とのみ対戦を行います(0-indexedにしたことに気を付けてください)。
第2ラウンドについて考えてみると、0,1番の人は2,3番の人と、4,5番の人は6,7番の人と対戦を行うことになります。
これを繰り返すと、
第ラウンドでは、人ごとにグループ分けをして、若い番号の人がいるグループから順番に0,1,2...と番号を振り、その後0と1、2と3…グループで対戦を行います。
なので、まずをで割った値を求めます(これをとします、切り捨てです)。すると、これがグループ番号となるので、あとはが偶数ならグループと、奇数ならグループと対戦を行います。
そして、グループの先頭は、となります。そこから人が、今回番の人が対戦する可能性のある相手になります。
これにより、第ラウンドにおけるの対戦相手がわかったので、あとは遷移の式にしたがって計算をしていけば、答えを求めることができます。
Typical DP Contest B - ゲーム
解法
左右それぞれの山に積まれている物の合計個数の偶奇によって、どちらのターンかは一意に決まります。
が偶数のとき、左右の合計が奇数であれば、次は後攻、偶数であれば先攻です。
が奇数の場合はこの逆になります。
さて、次のようなDPを考えていきます。
- 左の山の物の個数が個、右が個であったとき、ここからお互いが最適に動いた場合に得られる、すぬけ君が選んだ物の価値の合計
こうすることで、答えはを見ればいいことがわかります。
また、初期状態は、です。
さて、左右の山に積まれた物の個数の合計によってターンがどちらかが変わるので、左が個、右が個の山になっていた場合のそれぞれについて最適な行動を考えてみます。
左が個、右が個で先攻だったパターン
左から物をとると、その価値はであり、右からとった場合は、です。
それ以降お互いが最適な行動をした場合のすぬけ君の合計価値は、前者のパターンが、後者がであるので、この値と、このターンでとった物の価値を合計して、より良い方を選べばよいです。ということで、
左が個、右が個で後攻だったパターン
このターンでは、左と右どちらを選んでもすぬけ君の合計価値自体は変化がないです。が、すめけ君は、すぬけ君の合計価値ができるだけ小さくなるように行動をするので、
となります。
あとは、この遷移をもとにしてDPをしていきます。今の状態がどちらのターンなのかに気を配る必要があります。
そして、を見れば、最終的な答えがわかります。