はじめに
最近またちょくちょく参加しているので記録を残しておく。
成績:ABC3完(650, unrated)
A
nが奇数なら1つ、偶数なら2つの=が中央に来る。文字列を掛け算で扱えるのはpythonならではなのだろうか。
n = int(input())
if n%2 == 0:
print("-"*((n-2)//2) + "==" + "-"*((n-2)//2))
else:
print("-"*((n-1)//2) + "=" + "-"*((n-1)//2))
B
ちょっと難しい。5枚のカードがフルハウスになる時、カードがソートされていれば[1,1,1,2,2]のように前3枚が同じパターンか、[1,1,2,2,2]のように後ろ3枚が同じパターンかしかないため、それを判定する関数を定義してカードの選び方を全探索した。
A = list(map(int,input().split()))
#5枚のカードがフルハウスになるか判定する関数を定義
def check(cards): #cardsはソートされている必要がある
if cards[0] == cards[1] and cards[1] == cards[2] and cards[2] != cards[3] and cards[3] == cards[4]:
return True
elif cards[0] == cards[1] and cards[1] != cards[2] and cards[2] == cards[3] and cards[3] == cards[4]:
return True
else:
return False
#選ばない2つを選択
flag = False
for i in range(7):
for j in range(i+1,7):
choose = []
for k in range(7):
if k != i and k != j:
choose.append(A[k])
#choose内でフルハウスになるか判定
choose.sort()
if check(choose):
flag = True
if flag == True:
print("Yes")
else:
print("No")
5枚の選び方は選ばない2つを指定することで実装し、時間に余裕があるので途中で答えが見つかったとしても最後まで探索するようにした。5枚の選び方はitertools.combinationsを使った方が楽な気がする。
==Trueも書かなくていいのだがどうも何もないのが気持ち悪くて書いてしまう。
C
要は配列の中で一度しか登場しない数の中で最も大きいものの位置を出力すればOK。dictで登場回数を管理し、keyで降順にソートして登場回数が1の数字のindex+1を出力した。
n = int(input())
A = list(map(int,input().split()))
cnt = {} #登場回数をカウント
chk = set() #登場したかチェック
for i in range(n):
if A[i] in chk:
cnt[A[i]] += 1
else:
chk.add(A[i])
cnt[A[i]] = 1
cnt_sort = sorted(cnt.items(), key = lambda x:x[0], reverse=True)
for x, times in cnt_sort:
if times == 1:
print(A.index(x) + 1)
break
else:
print(-1)
なぜかdict中のkeyの有無をわざわざsetで管理している。dictのinも$O(1)$なのでdictを検索すればよいのだが、よく忘れる。index()は$O(n)$なので避けがちだがここでは1回きりの使用なので問題ないのが面白い。
D
時間内には方針が立たず、諦めて風呂に入っていたら解法を思いついた。
煙は全体が移動するため、最初に発生した煙を基準とするとそれ以降に発生した煙の相対的な位置は常に変わらない。ということで、最初に発生した煙の座標と、この煙に対する原点と高橋君の位置は毎秒計算する。「最初に発生した煙に対する後続の煙の座標」をsetで持っておき、先ほど計算した原点の位置がこのset中になければ煙が発生するので原点の位置をsetに加え、高橋君の位置がこのset中になければ0、あれば1を答えの配列に加算する。
n,r,c = map(int,input().split())
s = input()
ans = []
rows = set() #最初の煙から見た後続の位置関係をメモする
rows.add((0,0))
smk = [0,0] #最初の煙の位置
for i in range(n):
if s[i] == "N":
smk[0] -= 1
if s[i] == "W":
smk[1] -= 1
if s[i] == "S":
smk[0] += 1
if s[i] == "E":
smk[1] += 1
if (-smk[0], -smk[1]) not in rows: #原点に煙がなければ追加
rows.add((-smk[0], -smk[1]))
if (r - smk[0], c - smk[1]) in rows:
ans.append("1")
else:
ans.append("0")
print(''.join(ans))
公式解説では座標平面の方を動かすというアプローチが取られていたが、たぶんイメージの問題でやっていることはそんなに変わらないと思う。方針が経ってから5分くらいで書けたのでもう少し早く気づきたかったところだった。
Cまで解いて1時間くらい残せているのはよい傾向。Dを時間内に通したいところ。