京セラプログラミングコンテスト2023(AtCoder Beginner Contest 305)をPythonで解く

投稿日:  更新日:2023/09/11

Atcoder Python

B!
Daniel AgreloによるPixabay(https://pixabay.com/)からの画像

こんにちは, Shinoryoです.

今回は京セラプログラミングコンテスト2023(AtCoder Beginner Contest 305)を, Pythonで解いてみた結果を書き連ねていこうと思います.

A - Water Station

スタート地点にある給水所を0番目とし, それ以降も含めてi番目の給水所というようにナンバリングします. すると, Nkm地点に一番近い給水所の番号は, N/5を四捨五入することによって得られます. 最後にその番号を5倍すれば, その給水所が何km地点にあるかを求められます.

Pythonでは組み込み関数round()を用いることで, 四捨五入を行うことができます.

print(round(int(input()) / 5) * 5)

あるいは, 正数に対する四捨五入は, 「0.5を足して切り捨てる」というアルゴリズムによって得ることができます. これを利用すれば, 浮動小数点数演算による誤差を全く気にしなくてよくなります.

print(((int(input()) + 2) // 5) * 5)

B - ABCDEFG

今回の実装方針は, 以下のようになります.

  1. 隣り合う点同士の距離を格納した配列distanceを用意する.
  2. 配列distancei番目からj番目までのスライス, distance[i:j]を取得する.
    • ijは, 入力したアルファベットp, qに応じて適切な値にする.
  3. distance[i:j]の合計を出力する.

ijは, アルファベットA~Gを0~6に変換して取得すればよいです. 以下の例では, 文字列「ABCDEFG」からそのアルファベットを検索することによって取得しています.

# 入力
p, q = input().split()
# 入力したアルファベットを数字に変換
alphabet_list = "ABCDEFG"
p = alphabet_list.index(p)
q = alphabet_list.index(q)
# 距離配列のmin番目から(max-1)番目までの合計を出力
distance = [3,1,4,1,5,9]
print(sum(distance[min(p, q):max(p, q)]))

C - Snuke the Cookie Picker

#の数の各行の行合計を考えてみます. すると, 「0」「a」「a1」の3パターンに分かれます(ただし, aは行合計の最大値). 問題文の条件より, 「a1」のパターンは1行しか存在せず, その1行のどこかにすぬけ君がクッキーを取ったマスが存在することになります. 列に対しても同様であり, これによりすぬけ君がクッキーを取ったマスを求めることができます.

# 入力
H, W = list(map(int, input().split()))
S = [list(input()) for _ in range(H)]
# #の行合計・列合計を取得
hash_count_H = [sum(S[i][j] == "#" for j in range(W)) for i in range(H)]
hash_count_W = [sum(S[i][j] == "#" for i in range(H)) for j in range(W)]
# #の行合計が、最大値よりも1少ない列が答えの行
# 列に関しても同様
hast_lack_H = hash_count_H.index(max(hash_count_H) - 1)
hast_lack_W = hash_count_W.index(max(hash_count_W) - 1)
print(hast_lack_H + 1, hast_lack_W + 1)

D - Sleep Log

以下の関数f(x)を求めることがキーになります.

  • f(x):睡眠記録を取り始めてからx分後までに何分寝たか

この関数f(x)を用いれば, 各クエリに対して求める数はf(ri)f(li)であることが分かります.

f(Ai)のリストは, i=0から順々に計算していくことで求めることができます. そこから任意のxに対するf(x)は, 以下のようにして求めることができます.

  1. Aj1x<Ajとなるjを探す.
  2. f(x)を以下の式によって求める: (1)f(x)=f(Aj1)+(f(Aj)f(Aj1))×xAj1AjAj1.

なお, f(Aj)f(Aj1)AjAj1または0のいずれかです. つまり, 式(1)を以下のように書き換えることができます: (2)f(x)={f(Aj1)+(xAj1)if f(Aj)f(Aj1)>0,f(Aj1)others.

import bisect
def func(x, A, A_accum):
x_index = bisect.bisect(A, x)
return A_accum[x_index - 1] + (A_accum[x_index] - A_accum[x_index - 1] > 0) * (x - A[x_index - 1])
# 入力
N = int(input())
A = list(map(int, input().split()))
# A_accum[i] = f(A[i])
# f(x):睡眠記録を取り始めてからx分後までに何分寝たか
A_accum = [0 for _ in range(N + 1)]
for i in range(1, N):
A_accum[i] = A_accum[i - 1] + (i % 2 == 0) * (A[i] - A[i - 1])
A_accum[N] = A_accum[N - 1]
# 各クエリに対してループ
for _ in range(int(input())):
# l, rの入力
l, r = map(int, input().split())
# 求めるのは、f(r) - f(l)
print(func(r, A, A_accum) - func(l, A, A_accum))

E以降

E以降は私の能力不足故に省略いたします.

参考にしたサイト等

Search

About Me

自分の写真
理系大学生でした. Bloggerを利用して発信を行っています.

Labels