AtCoder ABC206 個人的メモ
所感
abc3完
A - Maxi-Buying
float型を小数点以下切り捨てでint型にするには、組み込み関数int()の引数にfloatを入れればおk
浮動小数点の誤差を考慮すると、
N = int(input())
cal = int(N * 1.08)
if cal < 206:
print("Yay!")
elif cal > 206:
print(":(")
else:
print("so-so")
B - Savings
問題文通りにシミュレーションすればおk。
ループの上限設定間違えて1wa
range関数の引数が
N = int(input())
coin = 0
for i in range(N + 10):
coin += i
if coin >= N:
break
print(i)
C - Swappable
1つ目の条件
ここから2つ目の条件を満たさない場合を除く。
ある数が
よって、各数においてこの値を引いていけばおk.
from math import comb
from collections import Counter
N = int(input())
A = list(map(int, input().split()))
ans = comb(N, 2)
cnt = Counter(A)
for i in cnt.keys():
ans -= comb(cnt[i], 2)
print(ans)
D - KAIBUNsyo
これは
この時、
しかし、問題の例1のような場合ではもう少し複雑になる。
例1の
この組み合わせの1つ目と2つ目に注目する。
1つ目の組み合わせから
ここで問題文より、ある数を置換する際は同じ数を全て置換しなければならないので、ある時に同じ数になっている要素は最終的にも同じ数になっているはず。
よって、1つ目の組み合わせの
従って、例1では
3つ目の組み合わせ
その際の操作回数は
例1では
以上をまとめると以下の実装で解けそう。
-
となっている組み合わせを探す。B_i\not ={C_i} - 同じ数同士で組み合わせを連結する。
- 各組み合わせごとに
を計算する。(組み合わせの要素数)-1 - その総和が解。
で、要素の連結とか連結後の成分の大きさの計算とかを実装するにはunion-findを使えばおk。
class UnionFind:
"""Union-Find(素集合データ構造(disjoint-set data structure)に対しての操作)"""
def __init__(self, n: int):
"""
Constructer(Initialize parameter in this class)
Parameters
----------
n : int
Number of node
Yields
-----
root : list
When value is postive, express root of the node.
When it is negative, express this node is root and size of set.
"""
self.root = [-1] * n
def find(self, x: int) -> int:
"""
Search root of node x
Parameters
----------
x : int
node x
Returns
-------
x : int
Root of node x
"""
if self.root[x] < 0:
return x
self.root[x] = self.find(self.root[x])
return self.root[x]
def unite(self, x: int, y: int) -> bool:
"""
Unite two set including node x and node y into one set.
Parameters
----------
x, y : int
Node number
Returns
-------
unite_result : bool
False : Already two node include same set.
True : United
"""
x = self.find(x)
y = self.find(y)
if x == y:
return False
if self.root[x] > self.root[y]:
x, y = y, x
self.root[x] += self.root[y]
self.root[y] = x
return True
def is_same(self, x: int, y: int) -> bool:
"""
Determine if x and y are in same set.
Parameters
----------
x, y : int
Node number
Returns
-------
result : bool
Determining result
"""
return self.find(x) == self.find(y)
def size(self, x: int) -> int:
"""
Return size of set including node x.
Parameters
----------
x : int
Node number
Returns
-------
Size of set : int
"""
return self.root[self.find(x)] * -1
N = int(input())
A = list(map(int, input().split()))
union = UnionFind(max(A) + 1)
# 解説文中のB,Cがそれぞれfront、backに対応
front = A[:N // 2]
back = A[-(-N // 2):][::-1]
for i in range(N // 2):
if front[i] == back[i]:
continue
# 手順1.と2.をunion-findで同時に行う
union.unite(front[i], back[i])
ans = 0
# 各組で重複して計算することが無いようにして総和を計算
seen = set()
for a in A:
root = union.find(a)
if root in seen:
continue
seen.add(root)
ans += union.size(root) - 1
print(ans)
参考
問題の解説
union-findは↓(ACL登場以前に公式解説動画で使ってたライブラリ)を参考に作っといたライブラリ
pythonでのunion-find解説
Discussion