ABC237の参加記録です。
前回、前々回のABCがうまくいって800までもう少しまで来ました。今回のABCでパフォーマンスが1,000を超えたら、おそらくレート800を超えそうです。
レートは関係なく、楽しめたら良いな。と思いつつも、意識せずにはいられない状態で参加しました。
使用言語はPython3です。レートは800弱です。
自分が理解した内容を書いていきます。
A – Not Overflow
標準入出力と比較演算子、累乗計算(またはシフト演算子)を知っていますか。が問われる問題。
累乗の計算は、Python3では、**
で書けますね。
print(2**3)
# 8
また、2の累乗の場合は、右シフト演算子 <<
でも同様のことができますね。
print(1<<3)
# 8
今回は、シフト演算子を利用したコードを書きました。
2の31乗した数字をXと置いて、マイナスX以上、X未満かを判定すればOKですね。
イコールを含む場合と、含まない場合に注意する必要があります。
# AtCoder Beginner Contest 237
# A - Not Overflow
N = int(input())
X = 1<<31
if -X <= N < X: # -X以上 X未満
print("Yes")
else:
print("No")
B – Matrix Transposition
行列の転置が書けますか。が問われる問題。
私はnumpyのT属性で取得しました。numpyの転置に関しては、ここのページがわかりやすいかと思います。
# AtCoder Beginner Contest 237
# B - Matrix Transposition
import numpy as np
H, W = map(int,input().split())
A = []
for _ in range (H):
l = list(map(int,input().split()))
A.append(l)
arr = np.array(A)
ans = arr.T
for row in ans:
print(*row)
上記コードはPyPy3だとREが出るため、Python3で出す必要があります。
PyPy3ではnumpyを利用できないためですね。
このほか、zip()
を利用する方法もあります。
私は、このコードは中身を理解するまでに時間がかかりました。
H, W = map(int,input().split())
A = []
for _ in range (H):
l = list(map(int,input().split()))
A.append(l)
for row in zip(*A):
print(*row)
勿論、問題文にある通り、愚直に B[i][j] を A[j][i] として書き込んでしまう方法でもACします。
H, W = map(int,input().split())
A = []
for _ in range (H):
l = list(map(int,input().split()))
A.append(l)
B = [[None for i in range(H)] for j in range (W)]
for i in range (W):
for j in range (H):
B[i][j] = A[j][i]
for row in B:
print(*row)
C – kasaka
回文判定が出来るか、場合分けを漏れなく検討できるかが問われる問題。
まず、回文判定については、入力れれる文字をSとして、以下の2パターンで判定できます。
# 回文判定1
for i in range(len(S)//2):
if S[i] == S[-1*(i+1)]:
continue
else:
print("No")
exit()
print("Yes")
# 回文判定2
if S==S[::-1]:
print("Yes")
else:
print("No")
スライスを使用して、一致かどうかを判定するほうがわかりやすいと思います。
私は、コンテスト中は、for文で判定する方法で提出しました。
次に、問題文にあるように、文字列の先頭に”a”をいくつか付け加えることを考えます。
これは、末尾の”a”をいくつか取り除くことと同じ意味になりますね。
先頭と末尾に連続する”a”の個数を数えて、場合分けすると、以下の通りになります。
- 先頭に連続する”a”と、末尾に連続する”a”の数が同じ場合。
- 先頭の連続する”a”のほうが、末尾に連続する”a”よりも少ない場合。
- 先頭の連続する”a”のほうが、末尾に連続する”a”よりも多い場合。
1.の場合は、先頭と末尾の”a”の個数は一緒なので、そのまま回文判定すれば良いです。
2.の場合は、先頭に”a”をいくつかつけて回文判定すれば良いですね。実際には、末尾の”a”を多い分だけ取り除きました。
3.の場合は、この時点で回文ではないことがわかっていますが、そのまま回文判定しても、False として判定されます。
つまり、2.の場合だけ、追加の処理を記述すればOKになります。
あとは、回文判定して、結果を出力すればACしますね。
# AtCoder Beginner Contest 237
# C - kasaka
S = list(input())
# Sの先頭に連続して存在する"a"の数を数える
a_cnt_left = 0
for i in range (len(S)):
if S[i] != "a":
break
else:
a_cnt_left += 1
# Sの末尾に連続して存在する"a"の数を数える
a_cnt_right = 0
for i in range (len(S)):
if S[-1*(i+1)] != "a":
break
else:
a_cnt_right += 1
# 末尾の"a"の数が多い場合、同じになるまで取り除く
if a_cnt_right > a_cnt_left:
for i in range(a_cnt_right - a_cnt_left):
S.pop()
# 回文判定
if S==S[::-1]:
print("Yes")
else:
print("No")
私は場合分けの3.のパターンに気づかずに提出してWA出しました。
今回のコンテストでレーティング800を超えることが出来ました!
「AtCoderで緑になる。」は、昨年(2021年)の目標でした。1月遅れですがようやく達成しました。
水色目指して今後も精進していきます。
コメント