[パナソニックグループ プログラミングコンテスト2024(AtCoder Beginner Contest 354)] 参加記録
パナソニックグループ プログラミングコンテスト2024(AtCoder Beginner Contest 354)に参加しました。
4冠です。
9時時点で PC の前に座れなかったので、タイムロスが大きいです。
計画的に行動します……
A - Exponential Plant
考え方
シンプルに植物の高さを保存して、
ちなみに、
def solve(h: int) -> int:
ans = 0
for i in range(128):
ans += 2**i
if ans > h:
return i + 1
if __name__ == "__main__":
H = int(input())
print(solve(H))
感想
非常にシンプルな問題でした。
始まった瞬間 PC の前におらず、スマホでやったら普通に RE しました。
B - AtCoder Janken 2
考え方
問題文通りの処理です。
まず、ユーザー名をキーに辞書順に並べます。
def solve(n: int, sc: list[tuple[str, int]]) -> str:
sorted_sc = sorted(sc)
t = sum(c for s, c in sc)
return sorted_sc[t % n][0]
if __name__ == "__main__":
N = int(input())
SC = [tuple(input().split()) for _ in range(N)]
SC = [(s, int(c)) for s, c in SC]
print(solve(N, SC))
感想
問題文通りの処理でした。
できるだけシンプルに書くことを心がけました。
C - AtCoder Magics
考え方
問題文より残るカードの集合が一意に定まるので、取り除くのではなく 組み込んでいく 処理と考えます。
取り除く系の問題は、最終成果物が一意なら、逆に組み込むとか組み立てるとか考えると計算量が削減できて嬉しいことが多いです。
グラフの辺を取り除く問題にこのパターンを見たことがあります。
最終的な出力は元のカードのインデックスなので、カードのインデックスとセットにした上で、
これはカードを追加していく順番なのですが、足していくカードは強さの面では既存のカード全てより弱いことが保証されます。
そのため、既存のカードのいずれかよりコストが高いかどうかを確認して、高くないなら追加します。
このとき、
ここで、既存のカードのいずれかよりコストが高いか確認する時、既存のカードの最小値よりも大きいかどうかを確認すればいいことに気がつけば、計算量を一回あたり
ということで、最小値を保存し、それよりも大きくないなら追加するという処理を行えば全体の計算量
def solve(n: int, ac: list[tuple[int, int]]) -> tuple[int, list[int]]:
sorted_ac = sorted(zip(ac, range(1, n + 1)), reverse=True)
# print(sorted_ac)
rtn: list[int] = [sorted_ac[0][1]]
cost_min = sorted_ac[0][0][1]
for i in range(1, n):
# print(i, sorted_ac[i])
cost = sorted_ac[i][0][1]
if cost_min < cost:
continue
rtn.append(sorted_ac[i][1])
cost_min = cost
return len(rtn), sorted(rtn)
if __name__ == "__main__":
N = int(input())
AC = [tuple(map(int, input().split())) for _ in range(N)]
ans, res = solve(N, AC)
print(ans)
print(*res)
感想
まず、グラフの問題の衝撃がすごかったので、方針はすぐに立ちました。
そこから計算量からどうにか処理したいと考えました。
すると、最小値だけをみればいいと気がつけたので、それを実装しました。
10分ちょっとで解けました。
9時ぴったりに PC の前に座れていれば、ここまで15分で解けて E 問題に取り掛かれたかもしれません。
バイトから帰ってくるのが7時の予定だったんですけどね。
D - AtCoder Wallpaper
考え方
問題の図からヒントを得ます。
まずは、入力が全て整数なので、座標系ではなくマス目のように考えます。
すると、
まだ考慮できないところを考えると、右側の 0~3 列分です。
もし高さが偶数ならここまでで全て計算済みになるので、そのまま出力します。
高さが奇数の場合、最後の 1 列分を考えます。
これは残りの列に応じて変わってくるので、1マスずつ計算すればわかりやすいです。
残りの 1~3 マスの座標は剰余をとって全て正にしておくと計算がしやすいです。
Python は仕様上正の数で剰余を取れば正の数になるので、そのまま計算しても大丈夫です。
これを残りのマス目に対して計算していけば、全てのマス目の面積が求まります。
最後に
def solve(a: int, b: int, c: int, d: int) -> int:
rtn = 0
width = c - a
w_set, w_mod = divmod(width, 4)
height = d - b
rtn += w_set * height * 4
# print(f"4set: {rtn}")
h_set, h_mod = divmod(height, 2)
c1_mod = (c - w_mod) % 4
for _ in range(w_mod):
# print(f"{c1_mod=}")
if c1_mod == 0:
rtn += h_set * 3
elif c1_mod == 1:
rtn += h_set * 3
else:
rtn += h_set
c1_mod += 1
c1_mod %= 4
# print(f"h_set: {rtn}")
if h_mod == 1:
c1_mod = (c - w_mod) % 4
d_mod = (d - 1) % 2
# print(f"{c1_mod=}, {d_mod=}")
for _ in range(w_mod):
# print(f"{c1_mod=}")
if c1_mod % 2 ^ d_mod % 2:
# print("add tri")
rtn += 1
elif c1_mod < 2:
# print("add squ")
rtn += 2
c1_mod += 1
c1_mod %= 4
return rtn
if __name__ == "__main__":
A, B, C, D = map(int, input().split())
print(solve(A, B, C, D))
感想
最後の残りの 1~3 マスの処理に手こずり、WA を出しました。
試しに、
テストケースはどんな時でも重要ですね。
Discussion