[AtCoder Daily Training ALL 2024/06/04 17:30start] 参加記録
AtCoder Daily Training ALL 2024/06/04 17:30start に参加しました。
A ~ G の7完でした。
H 問題に24分残しておけましたが、方向性は合っていたものの、違うところを同じ方向に進んでいたため、解けませんでした。
H 問題についてはこの記事にはありません。
残り時間的に、「自分も成長したなあ」と思いましたが、難易度が低いだけだったので精進します。
A - A Recursive Function
もしくは こちら
考え方
再帰的に定義された階上関数です。
定義通りに実装します。
def solve(n: int):
if n == 0:
return 1
return n * solve(n - 1)
if __name__ == "__main__":
N: int = int(input())
result: int = solve(N)
print(result)
感想
やるだけ。
B - Wrong Answer
もしくは こちら
考え方
答えの範囲が
等しくなければ、それが答えです。
答えが複数ありますが、最初に見つかったもので十分です。
def solve(a: int, b: int) -> int:
for i in range(10):
if i != a + b:
return i
raise ValueError("No solution found")
if __name__ == "__main__":
A, B = map(int, input().split())
result = solve(A, B)
print(result)
感想
ユーザースクリプトの AtCoder Easy Test v2 が使えないため、提出時少し不安でした。
答えが複数あるタイプは、この心理的なプレッシャーが苦手です。
C - 3-smooth Numbers
もしくは こちら
考え方
一見制約が大きいように見えますが、
よって、
def solve(n: int) -> bool:
while n % 2 == 0:
n //= 2
while n % 3 == 0:
n //= 3
return n == 1
if __name__ == "__main__":
N: int = int(input())
result: bool = solve(N)
print("Yes" if result else "No")
感想
計算量を確かめたら、あとはやるだけ。
指数系はすぐに値が大きくなるので、実は計算量が小さいパターンが多い気がします。
D - At Most 3 (Judge ver.)
もしくは こちら
考え方
Python の itertool.combinations
を使って、
ただし、問題文が 3個以下 なので、
そのため、今回は重さ
答えるのは、
そのため、選んだ重りの重さの和が set
に格納して、最後にその set
の長さを出力します。
from itertools import combinations
def solve(n: int, w: int, a: list[int]) -> int:
a.append(0)
a.append(0)
sum_set: set[int] = set()
for s, t, u in combinations(a, 3):
# print(s, t, u)
if s + t + u <= w:
sum_set.add(s + t + u)
return len(sum_set)
if __name__ == "__main__":
N, W = map(int, input().split())
A = list(map(int, input().split()))
result = solve(N, W, A)
print(result)
感想
全探索できる問題は、全探索で解くのが一番楽です。
E - Peak
もしくは こちら
考え方
とりあえず、プレゼントが何個目かはどうでもいいので、昇順でソートします。
また、
制約が
そのため、今見ているプレゼントの前からの数と、
二分探索(同じ値がある場合はもらえないので、左側を返す) で
from bisect import bisect_left
def solve(n: int, m: int, a: list[int]) -> int:
a.sort()
ans: int = 0
for i, a_i in enumerate(a):
index = bisect_left(a, a_i + m, i + 1)
ans = max(ans, index - i)
return ans
if __name__ == "__main__":
N, M = map(int, input().split())
A = list(map(int, input().split()))
result = solve(N, M, A)
print(result)
感想
計算量から方法を推測するというのが身についてきた気がします。
二分探索で左か右かというのもすぐに判断できたのはいいと思います。
やけに簡単だなと思ったら案の定 diff 299 でした。
F - Counting 2
もしくは こちら
考え方
まず、昇順にソートすることで、インデックスがそのまま背の低い順になります。
あとは各
左を返す二分探索であれば、身長が
降順で右を返す二分探索をすれば一発でもとまるので、そちらの方が楽です。
from bisect import bisect_left
def solve(n: int, q: int, a: list[int], x: list[int]) -> list[int]:
a.sort()
ans: list[int] = []
for x_i in x:
index = bisect_left(a, x_i)
ans.append(n - index)
return ans
if __name__ == "__main__":
N, Q = map(int, input().split())
A = list(map(int, input().split()))
X = [int(input()) for _ in range(Q)]
result = solve(N, Q, A, X)
print("\n".join(map(str, result)))
感想
2回連続二分探索?と思いました。
気分は3回連続アが解答欄に並んだ感じです。
しかし、二分探索で十分解けるなと思ったので、やってみたら案の定できました。
こちらも簡単だなと思ったら diff 194 とだいぶ低めでした。
降順にソートすればいいと気がついたのは、この記事を書いている今です。
文字量的にはこっちの方が少ないですが、ほぼ誤差ですね。
G - Loong and Takahashi
もしくは こちら
考え方
問題文の意味が分かりづらいのでサンプルケースからヒントを得ます。
すると、 "T"
を中心にして、外側から数字を並べれば求めるべき解が得られることが分かります。
よって、とりあえず中心に "T"
を置いて、左上から中心に向かって数字を並べていきます。
なお、実装例は変数名に釣られて、 Direction
のメンバが明らかにおかしいですが、結局は題意を満たすので問題ありません。
from enum import Enum
from typing import Literal, Self
class Direction(Enum):
UP = (0, -1)
DOWN = (0, 1)
RIGHT = (1, 0)
LEFT = (-1, 0)
def next(self) -> Self:
match self:
case Direction.UP:
return Direction.RIGHT
case Direction.RIGHT:
return Direction.DOWN
case Direction.DOWN:
return Direction.LEFT
case Direction.LEFT:
return Direction.UP
def move(self, x: int, y: int) -> tuple[int, int]:
dx, dy = self.value
return x + dx, y + dy
def solve(n: int) -> list[list[Literal["T"] | int]]:
ans: list[list[Literal["T"] | int]] = [[""] * n for _ in range(n)]
ans[n // 2][n // 2] = "T"
x: int = 0
y: int = 0
direction: Direction = Direction.RIGHT
for i in range(1, n**2):
ans[x][y] = i
next_x, next_y = direction.move(x, y)
if (
next_x < 0
or next_x >= n
or next_y < 0
or next_y >= n
or ans[next_x][next_y] != ""
):
direction = direction.next()
next_x, next_y = direction.move(x, y)
x, y = next_x, next_y
return ans
if __name__ == "__main__":
N: int = int(input())
result: list[int] = solve(N)
for res in result:
print(*res)
感想
サンプルケースにヒントがあることはよくあります。
問題文の理解に戸惑ったら、サンプルケースが詳しいパターンが多いので、よく見ることをおすすめします。
Direction
のメンバがおかしいのは x
と y
が高さと幅を表しているためです。
そのため、 UP
で y
を減らして上に移動するつもりが、実際には左に移動してしまっています。
以降もメンテナンスするコードなら絶対直しますが、この問題は一発で通ったのでそのままにしました。
一回でも WA が出たら直そうとは思ってました。
Discussion