mery's Notes

めりーがプログラミングしたりします。

MENU

AtCoder Beginner Contest (ABC) 228 Pythonで参戦しました。 A,B,C問題解説あり。

前回のやつ

mery-kirokudayo.hateblo.jp f:id:mery_poke:20211121095147p:plain

こんばんわ。めりーです。

寒くなってきたので、押し入れからマフラーとセーターを引っ張り出して来たら、驚くほど汚れてたので人生初クリーニングに出してきました。
まぁ、去年使い終わったのをそのまま放置してたらこうなりますよね・・・。

というわけで、トヨタシステムズプログラミングコンテスト2021(AtCoder Beginner Contest 228)参戦してきました。
今回はA,B,C問題まで解けたので、感想&解説しまーす。

言語はPython、提出はPyPyです。

目次

A問題 On and Off

On and Off

問題文

A - On and Off

S時に電気をつけ、T時に電気を消します。
X時30分に電気は付いているでしょうか?
という問題。

方針は、
1. 入力する
2. SからTの間に0時を超えているかでif文で判別
3. 2の条件下で判定する

という方針でやりました。

コード

s,t,x = map(int,input().split())
if s <= t:
    if s<=x<t:
        print("Yes")
    else:
        print("No")
else:
    if s<=x or x<t:
        print("Yes")
    else:
        print("No")

解説です。

if s <= t:
    if s<=x<t:
        print("Yes")
    else:
        print("No")

まず、0時をまたがないバージョンです。
この場合は単純に、SからTの間にXがあればYesを出力します。
X = Tの場合はNoになります。
T時00分に電気を消して、X(=T)時30分に電気を消すからです。

else:
    if s<=x or x<t:
        print("Yes")
    else:
        print("No")

0時をまたぐバージョンです。
T(消灯時刻)~S(点燈時刻)の範囲外にあればYesです。
言い換えると、X < T もしくは、 S <= X にあればYesです。

B問題 Takahashi's Secret

Takahashi's Secret

問題文

B - Takahashi's Secret

高橋君にはN人友達がいます。
ある日、秘密がX君にばれます。
友達i君は秘密をAi君にばらします。
高橋君は何人の友達に秘密がばれるでしょうか?
という問題。

手順としては、
N個の要素を持った配列を全要素「0」で作ります。(以下フラグと呼ぶ。)
友達i君が秘密を知ったらフラグの要素iを1にします。
それを愚直に問題文の通りに実装すればOKです。

方針は、
1. 入力
2. フラグ建設
3. 順番に処理してく
4. 出力

という感じでやってきました。

コード

n,x = map(int,input().split())
a = list(map(int, input().split()))

x -= 1
ans = [0]*n
ans[x] = 1

for i in range(n):
    if ans[a[x]-1] == 0:
        ans[a[x]-1] = 1
        x = a[x]-1
    else:
        break
print(sum(ans))

解説してきます。

x -= 1
ans = [0]*n
ans[x] = 1

まず、Xが1始まりなので、0始まりにするために、Xを-1します。
ansをフラグとして作成します。
そして、起点になってる友達Xのフラグを1にします。

for _ in range(n):
    if ans[a[x]-1] == 0:
        ans[a[x]-1] = 1
        x = a[x]-1
    else:
        break

メイン部分
友達XがA[x]にチクるので、A[x]のフラグを1にします。
そして、XをA[x]に更新します。
それを繰り返していきます。

この処理が終了するのは、伝えられた友達が秘密を知っていた場合です。
つまり、フラグを1に変更する前にフラグが1だった場合、終了します。

C問題 Final Day

Final Day

問題文

C - Final Day

N人が4日間試験を受けます。
各日、300点満点です。
人iが4日目のテストで、上位K人に入ることはあり得るか?
という問題。

とりあえず、人iの3日目までの成績に300(4日目のテストの満点)足して、他の人の3日目までの成績と比べて上位K位以内に入れれば可能性はありそうです。
上位K番目の人の点数は、ソートを使えば簡単にゲットできそうです。
なので、全ての人iについて全探索すればよさそうです。

というわけで、方針
1. 入力。
2. 現時点での合計点を計算して、ソート。
3. 各人iについて全探索する。
4. 人iの合計点に300足したものとソートした上位K番目の合計点とを比較して出力。

コード

n,k = map(int, input().split())
p = []
for _ in range(n):
    P = list(map(int, input().split()))
    p.append(sum(P))

p1 = sorted(p,reverse=True)

for i in range(n):
    
    if p[i] + 300 >= p1[k-1]:
        print("Yes")
    else:
        print("No")

解説してきます。

for _ in range(n):
    P = list(map(int, input().split()))
    p.append(sum(P))

Pの入力をするときに、合計値にして入力してます。
入力時に計算しておくと、配列Pの中に入るのが、

P = [人1の3日目までの合計点、人2の3日目までの合計点,...]

となります。
なので、この後ソートするときに楽になります。

p1 = sorted(p,reverse=True)で、ソートします。p1は配列pとは別の配列なので注意。
今回は降順(3,2,1みたいなやつ)で並べ替えてます。
なので、上位K番目の人の得点がp1[k-1]でわかります。

for i in range(n):
    
    if p[i] + 300 >= p1[k-1]:
        print("Yes")
    else:
        print("No")

全探索パート
i番目の人の3日目までの得点に300足して(p[i]+300)、それが上位K番目の人の得点(p1[k-1])より高ければYes、小さければNoを出力します。
それだけ。

今回のコンテストはD問題にも手を出してみたのですが、TLEに苦しんで正解できませんでした。
くそおおおおおおお

それでは。