Open21

競プロ

kyasbalkyasbal

NKが互いに素であるなら、

S + nK \equiv 0 (mod N)

となる n を求めればよいので、

n \equiv (N-S)K^{-1} (mod N)
kyasbalkyasbal

多分これ、互いに素じゃないときのほうが問題なんだろうな。

kyasbalkyasbal

NKが互いに素でないとする。
つまり、NKが公約数qを持つとしたとき、

S + nqK^\prime \equiv 0 (mod qN^\prime)

となり、 Sqで割れるならば、これはN^\primeの輪をK^\primeを一回あたりに動く距離として回っていることと等しい。

例えば、 qが2ならば、Nの二席分を一つの単位として見ているような感じ。N,Kが互いに素ならば、いつか玉座にたどり着く。逆に qがあるという事は、その一緒に見た単位の中に一つだけ常に通る椅子があり、それ以外は常に通らない。Sqで割れないというのは、q通りできる巡回するパスの中で、0を通らないパスにいることと同じ。

kyasbalkyasbal

実際にLCS風に DPを行うなら、空間計算量は O(MN)必要なはず。これは十分間に合いそう。
計算量も O(MN)程度になるはず。これも問題なさげ。

d_{i,j}:= Aのi番目、Bのj番目までで達成可能なx+yの値

として計算できない?

kyasbalkyasbal

ある i ,j番目を比較しているときに A_i = B_jであるとする。このときはx+yに寄与しない。

kyasbalkyasbal
d_{i,j} := Aのi番目、Bのj番目までで達成可能なyの値

とすれば、

d_{k,k} + N-k + M - k

で最小値を探せばよいのではないか。

kyasbalkyasbal

長いほうから、長い分だけ消せばよいのでは?

短いほうからも消す意味はないのでは。

kyasbalkyasbal

便宜上、 Aのほうが長いとする。

d_{i,k}:= Aのi番目まで見て、k個消したときにA_s=B_{s+k}

を満たせる最大の数

kyasbalkyasbal

Aのi番目を見ているときは、Bのi-k番目を見ているはず。
この時、これが等しいなら、消す必要はない、等しくないとき、消したとして状況を更新していく動的計画法ができるのでは?

d_{i+1,k}=d_{i,k}+1 (A_i = B_{i-k}のとき)
d_{i+1,k}=max(d_{i,k-1},d_{i,k}) (A_i != B_{i-k} のとき)
kyasbalkyasbal

いや、これはだめかも

1 3 4
2 1 3

の時、消さなければ 3、1つめと3つめを消せば、 2 + 0 = 2

となる。つまり、長いほうだけ操作すればよいという仮説が誤り。

kyasbalkyasbal

結局のところ、LCSに近い方法になるのではないか。

今、i,j文字目を見ているときにスコアが変わるのは、

i文字目かj文字目を削除するケース
i-1,j文字目を見ているスコア + 1
i,j-1文字目を見ているスコア + 1

i文字目、j文字目を採択するケース
i-1,j-1文字目を見ているスコア + c

ただし、A[i]=B[j] なら c = 0, それいがいは1とする。

とすればよさそう。

kyasbalkyasbal

斜めに配列をなめる必要があるかと思ったが、通常の2重forで行うことができる。

def main():
    N,M = map(int,input().split())
    A = list(map(int,input().split()))
    B = list(map(int,input().split()))
    D = [[10**10] * (len(B)+1) for i in range(len(A)+1)]
    D[0][0] = 0
    for i in range(N+1):
        for j in range(M+1):
            if i > 0:
                D[i][j] = min(D[i][j],D[i-1][j] + 1)
            if j > 0:
                D[i][j] = min(D[i][j],D[i][j-1] + 1)
            if i > 0 and j > 0:
                D[i][j] = min(D[i][j],D[i-1][j-1] + (0 if A[i-1] == B[j-1] else 1))
    print(D[-1][-1])
main()

AC

https://atcoder.jp/contests/abc185/submissions/24942207

kyasbalkyasbal

幾何学的なアプローチか、bit DP的なアプローチを感じる。 Nの制約からしてbitDPはギリギリ可能そう。

dp_{S,i}=既に訪れたことがある都市がSで、最後にiにいるときの最小コスト
2^{17} = 131072(10^5程度)
O(N2^N)

は十分に高速そう

kyasbalkyasbal

考えてたこと

  • マンハッタン距離関係?
  • 点を固定して log(N) のオーダでその点に対する最大値が見つかる?
kyasbalkyasbal

実際には

  • 答えとなる値が可能になるかどうかの二分探索

どうやって気が付くべき?

  • 今回は制約からの気づきは難しい(無駄に大きいNが与えられているわけではない)
  • 数学的な考察をもうちょっと深める?