ABC135 D - Digits Parade
問題原文
問題要旨
数字と ?
からなる文字列 が与えられる。
?
を好きな数字に置き換えてできる整数のうち、 13で割って5余る数はいくつあるか?
ただし、先頭の0は許可される。
解法
すごいDPっぽいのでDPを考える。
まず「何番目までみたか?」の情報は基本なので採用。
というDPをまず考える。まぁ普通に無理。
無理な理由を考える。
として、2文字目まで考えた時に、13で割ったあまりは1。
3文字目まで考えた時のあまりは、5。これは、 ((27 * 10) + 8) % 5 と等しい。
次の数字を見るたびに、いままでの数字のうしろに0をつける →10倍すると考えるとわかりやすい。
結局、 「13で割ったあまりがなんになるか?」の情報もいる。
dpテーブルを考えると、 となる。
遷移に関しては、次の文字を見るたびに今までみてきた数字が左シフトしていくと考えると、
のとき
のとき
となる。
実装
S = input() N = len(S) MOD = 10 ** 9 + 7 # dp[i][j] := i文字目までみた時に13で割ってj余るような数の通り数 dp = [[0] * 13 for i in range(N + 1)] dp[0][0] = 1 for i, s in enumerate(S): for j in range(13): if s != '?': dp[i + 1][((j * 10) + int(s)) % 13] += dp[i][j] dp[i + 1][((j * 10) + int(s)) % 13] %= MOD else: for k in range(10): dp[i + 1][((j * 10) + k) % 13] += dp[i][j] dp[i + 1][((j * 10) + k) % 13] %= MOD print(dp[-1][5] % MOD)
感想
良い問題!!! 右に数字が追加されていく → いままでのを10倍 みたいなのを、パッと出せるようになりたいな