青になりたい

競技プログラミングの記録です

AtCoder Beginner Contest 135 D - Digits Parade

atcoder.jp
典型的なdpだが解けなかった。
いかにも競プロっぽいので、こういうのが解けるようになれば楽しそう。

問題概要

数字と?で構成される文字列Sがある。
?を数字に置き換えてできる整数のうち、13で割って5あまる数は何通りあるか。

制約

len(S) <= 10^5

解法

dp[i][j]を、i文字目まで見たとき、13でわった余りがjになる数の総数とする。
i+1文字目への遷移は、i+1文字目の数字がkとすると、
dp[i+1][(j*10+k)%13] += dp[i][j]
をj = 0,1,....12としたものになる。
(例えばdp[2][7]は2文字目まで見てあまりが7の総数なので、3文字目が5ならば、70+5を13で割ったあまりのところにそれを足してやる)
i+1文字目が?のときはkを0から9まで動かす。

# ABC 135 D - Digits Parade

S = input()
N = len(S)
dp = [[0 for i in range(13)] for j in range(N+1)]
# dp[i][j] := i文字目まで見たときに13でわった余りがjになる総数

MOD = 10**9 + 7
dp[0][0] = 1

for i in range(1,N+1):
    if S[i-1] == "?":
        for j in range(13):
            for k in range(10):
                dp[i][(j*10+k)%13] += dp[i-1][j]
                dp[i][(j*10+k)%13] %= MOD
    else:
        t = int(S[i-1])
        for j in range(13):
            dp[i][(j*10+t)%13] += dp[i-1][j]
            dp[i][(j*10+t)%13] %= MOD

print(dp[N][5])