ebisukeプログラミング初心者脱出黙示録

30歳を過ぎてから始めたプログラミングと競プロの記録。Pythonで取り組んでいます。Arduinoで電子工作も

AtCoder-ABC220 D - FG operation【Python解答例】

AtCoder Beginner Contest220のD問題についてPythonの解答例を記事にしていきます。
AtCoder Beginner Contest 220 - AtCoder



AtCoder Beginner Contest220 D - FG operation

D - FG operation

問題文

0 以上 9 以下の整数からなる長さ N の数列 A=(A 1​ ,…,A N​ ) があり、この順に左から右に並んでいます。

数列の長さが 1 になるまで、操作 F または操作 G を繰り返し行います。

操作 F :左端の 2 つの値 ( x,y とする ) を削除した後、一番左に (x+y)%10 を挿入する
操作 G :左端の 2 つの値 ( x,y とする ) を削除した後、一番左に (x×y)%10 を挿入する
なお、a%b は a を b で割った余りを意味します。

K=0,1,…,9 について、以下の問題に答えてください。

操作手順としてあり得るものは 2 N−1 通りありますが、このうち最終的に残る値が K となる操作手順は何通りありますか?
ただし答えは非常に大きくなる可能性があるので、998244353 で割った余りを求めてください。

制約

・2≤N≤10 ^5
・0≤A i​ ≤9
・入力は全て整数

解答例

mod = 998244353

n = int(input())

A = list(map(int, input().split()))

dp = [[0]*10 for _ in range(n+1)]

dp[0][A[0]] = 1
for i in range(n-1):
    y = A[i+1]
    for j in range(10):
        if dp[i][j] != 0:
            x = j
            xf = (x+y) % 10
            xg = (x*y) % 10

            dp[i+1][xf] = (dp[i+1][xf] + dp[i][x]) % mod
            dp[i+1][xg] = (dp[i+1][xg] + dp[i][x]) % mod

for i in range(10):
    print(dp[n-1][i])

解説

操作Fと操作Gを数列Aが最後に1項だけ残るまで繰り返したとき、最後の値がKになる操作手順がそれぞれ何通りか答える問題です。

動的計画法DPを用いて解きました。

dp[i][j]:i回操作を行ったとき最も左の値がjとなる操作手順のパターン数 としました。

初期条件として数列Aの左端がA[0]なのでdp[0][A[0]を1通りとします。

この条件で左からN-1までループさせました。
yはA[i+1]で、dp[i][j]が0でないときのみx = jとして処理を続けます。

処理Fを行ったときの値をxf、処理Gはxgとして計算します。
処理Fについてはdp[i+1][xf] = (dp[i+1][xf] + dp[i][x]) % modと、処理Gはdp[i+1][xg] = (dp[i+1][xg] + dp[i][x]) % modと更新していきました。

このループを抜けたあとに各Kの値を出力すればACです!



ABC220関連記事はこちら
ebisuke33.hatenablog.com
ebisuke33.hatenablog.com