競プロ
となる
多分これ、互いに素じゃないときのほうが問題なんだろうな。
つまり、
となり、
例えば、
PyPy 7.3.0では pow(K,-1,N)
は失敗する。
Python 3.8,2ではOK
地味な地雷だな
LCSのような話?共通ではなく、逆に異なるものを選んでいくのか?
実際にLCS風に DPを行うなら、空間計算量は
計算量も
として計算できない?
ある
とすれば、
で最小値を探せばよいのではないか。
長いほうから、長い分だけ消せばよいのでは?
短いほうからも消す意味はないのでは。
便宜上、 Aのほうが長いとする。
を満たせる最大の数
Aのi番目を見ているときは、Bのi-k番目を見ているはず。
この時、これが等しいなら、消す必要はない、等しくないとき、消したとして状況を更新していく動的計画法ができるのでは?
いや、これはだめかも
1 3 4
2 1 3
の時、消さなければ 3、1つめと3つめを消せば、 2 + 0 = 2
となる。つまり、長いほうだけ操作すればよいという仮説が誤り。
結局のところ、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とする。
とすればよさそう。
斜めに配列をなめる必要があるかと思ったが、通常の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
幾何学的なアプローチか、bit DP的なアプローチを感じる。 Nの制約からしてbitDPはギリギリ可能そう。
は十分に高速そう
ABC215 F
青問題
考えてたこと
- マンハッタン距離関係?
- 点を固定して
log(N)
のオーダでその点に対する最大値が見つかる?
実際には
- 答えとなる値が可能になるかどうかの二分探索
どうやって気が付くべき?
- 今回は制約からの気づきは難しい(無駄に大きいNが与えられているわけではない)
- 数学的な考察をもうちょっと深める?
転倒数が関係あることは十分分かる。
転倒数⇒Bitを使って、自分よりも左にある大きな数を足すことを繰り返せば求められる。