EDPC S - Digit Sum
桁和
考え方
ABCでいうと、E問題級。
いわゆる桁 DP。
free[i][r] を、i 桁目より後ろを自由に決めたとき、桁和を $D$ で割った余りが r になる個数とする。
これは、下の桁から順に作れる。
その事前処理をしておいて、上から順に桁を見ていく。
今見ている桁で $K$ の同じ桁より小さい値を置いた瞬間、それより後ろの桁は自由になる。
その自由になった後ろの桁の個数を、先に作った free から取り出せばよい。
具体的には、後ろの桁で必要な余りは $-(s + j) \bmod D$ になる。
ただし、$s$ は今見ている桁より上の桁和、$j$ は今の桁に置く値である。
これに対応する free[i][...] を答えに足していけば、$0$ 以上 $K$ 未満のパターン数になる。
問題は $1$ 以上 $K$ 以下なので、その分の補正を考える。
未満と以下の補正は、最初に $K$ に $1$ を足しておけばよい。
$0$ 以上と $1$ 以上の補正は、$0$ が必ず条件を満たすことから、単純に $-1$ しておけばよい。
計算量は $O(|K|D)$。
入力例1での動作
入力を受け取る。
k: 30
d: 4
まず k に $1$ を足す。
これにより、$0$ 以上 $31$ 未満の数を数え、最後に 0 の分を引く形にしている。
k: 31
free[i][j] を、i 桁目より後ろを自由に決めたとき、桁和を $d$ で割った余りが j になるものの数とする。
最下位桁より後ろには何もないので、次の状態から始まる。
free[1]: {1, 0, 0, 0}
下の桁を $1$ 桁自由に決めると、0 から 9 の $10$ 通りになる。
free[0]: {3, 3, 2, 2}
上から $1$ 桁目で、3 より小さい 0,1,2 を置く場合を数える。
0 を置く: free[0][0] = 3
1 を置く: free[0][3] = 2
2 を置く: free[0][2] = 2
ここまでで $7$ 通りである。
次の桁で 1 より小さい 0 を置く場合は、残り桁がないため追加は $0$ 通りである。
最後に 0 の分を引く。
7 - 1 = 6
よって答えは $6$ である。
注意点
答えは $10^9+7$ で割った余りを要求されているので、剰余類環の考えに従って処理する。
足し算をするたびに結果を % 1000000007 する。
別解
特になし。