ABC129 E - Sum Equals Xor
問題原文
問題要旨
非負整数からなる組 であって、以下の条件を満たすものの通り数を求めよ。
==
解法
ここから出てくる1111~とかは全部2進数です。
制約が桁dpをしろと言っている。。。
こういう場合には、「以下であることがまだ未確定にdpテーブル」と「以下であることがすでに確定しているdpテーブル」を考えるとうまくいく。
ところで、 のある桁のbitに注目した時には4通りの状態が取りうるが、与えられた条件や、繰り上がり等を考慮すると以下のように分類できる。
以下であることが未確定 & の ビット目が1
→ の2通り以下であることが未確定 & の ビット目が0
→ の1通り以下であることが確定 & の ビット目が1
→ の3通り以下であることが確定 & の ビット目が0
→ の3通り
また、 の ビット目が1の場合には、そのビットを0に確定させることで、「以下であることがすでに確定しているdpテーブル」へ遷移できる。
イメージとしては、 の上で、 と確定させる感じかな。。。
においては、 みたいなパターンがこれにあたる。
実装
dp問は先に遷移とかをしっかり理解しておけば、楽にかける気がする。。。?
サンプルが弱いので、愚直を書いてチェックするようにするとデバッグが楽になります。
L = input() MOD = 10 ** 9 + 7 # dp[i][flg] := 上からi番目の桁まで見た時に、L以下であることがflg(未確定/確定)であるような、条件を満たす組み合わせの通り数 dp = [[0] * 2 for i in range(len(L) + 1)] dp[0][0] = 1 for i, l in enumerate(L, start=1): if l == '0': dp[i][0] = dp[i - 1][0] dp[i][1] = (3 * dp[i - 1][1]) % MOD else: dp[i][0] = (2 * dp[i - 1][0]) % MOD dp[i][1] = (3 * dp[i - 1][1] + dp[i - 1][0]) % MOD print(sum(dp[-1]) % MOD)
余談
桁dp使わなくても解けるらしい。。。むぅ drken1215.hatenablog.com
(さすがけんちょんさん)
感想
前はdpは不可能、桁dpなんでとんでもないという感じだったんですが、復習はすっとできて嬉しさ。
- 先に紙の上で遷移を整理する(dpテーブルを書くのもおすすめ)
- いいサンプルを愚直を書いて自作する
とかが大事そうだなぁと思いました。