AtCoder Beginners Selectionを,Python3で取り組みます.
注:問題文は意訳しています.
- PracticeA - Welcome to AtCoder
- ABC086A - Product
- ABC081A - Placing Marbles
- ABC081B - Shift only
- ABC087B - Coins
- ABC083B - Some Sums
- ABC088B - Card Game for Two
- ABC085B - Kagami Mochi
- ABC085C - Otoshidama
- ABC049C - 白昼夢
- ABC086C - Traveling
- 終わりに
PracticeA - Welcome to AtCoder
&a \\
&b~c \\
&s
\end{aligned}
&a+b+c~s
\end{aligned}
各言語でサンプルが与えられています.入力の受け取り方がわかり,次問以降で使えます.
以下はPython3のコードです.
# -*- coding: utf-8 -*- # 整数の入力 a = int(input()) # スペース区切りの整数の入力 b, c = map(int, input().split()) # 文字列の入力 s = input() # 出力 print("{} {}".format(a+b+c, s))
この問題で,「コードテスト」,「提出」,「提出結果」の確認方法がわかりました.
提出結果>全ての提出から,実行時間が短い回答を見られるのは,後々使えそうです.
ABC086A - Product
&a~b
\end{aligned}
\begin{cases}
\,\text{Odd} & (a\times b\text{\,が奇数の場合}) \\
\,\text{Even} & (a\times b\text{\,が偶数の場合})
\end{cases}
\end{aligned}
以前の問題を参考にすると,次で行けそうです.
a, b = map(int, input().split()) if a*b % 2 == 0: print('Even') else: print('Odd')
無事,正解でした.
「提出結果>全ての提出」で実行時間が短いものをみると,同じような回答でした.
コード長が短いものは,...ちょっとテクニカルなのでまだパスしておきます.
ABC081A - Placing Marbles
&s_{1}s_{2}s_{3}
\end{aligned}
&s_{1}+s_{2}+s_{3}
\end{aligned}
s = map(int, list(input())) print(sum(s))
ここで,
s = list(input())
とすると,リストの要素が文字列となるためsumをとるときにエラーが出ました(例えば,標準入力「101」に対して,sは「['1', '0', '1']」となります).
実行時間が短い回答で参考になったのは以下です.なるほど...
print(input().count("1"))
ABC081B - Shift only
&N \\
&A_{1}~A_{2}\cdots A_{N}
\end{aligned}
また,あとで気づきましたが,a_listはリストになっていません.リストにするにはこれにlist()を作用させる必要があります.
n = int(input()) ans = 1e9 a_list = map(int, input().split()) for a in a_list: i = 0 while a % 2 == 0: a = a // 2 i += 1 if i < ans: ans = i print(ans)
実行時間が短い回答例は,次が参考になります.
n = input() a = list(map(int, input().split())) ans = float('inf') for i in a: ans = min(ans, len(bin(i)) - bin(i).rfind('1') - 1) print(ans)
2進数に変換すれば,末尾のゼロの数=2で割れる回数となることを利用しています.本質的には,同じことをやっていますが,ループさせるより組み込み関数を使ったほうが早いということですね.組み込み関数bin()と文字列メソッドstr.rfindについては次に説明があります.
また,ansの初期値はなるべく大きい値にすれば良いので無限大になっています.これなら,入力される値の範囲が変わってもそのまま使える,ということですね.
ABC087B - Coins
&A \\
&B \\
&C \\
&X
\end{aligned}
&X = 500a + 100b + 50c \\
&(0\leq a \leq A, 0\leq b \leq B, 0\leq c \leq C)
\end{aligned}
単純に,全通り試す方法を考えました.
a = int(input()) b = int(input()) c = int(input()) x = int(input()) ans = 0 for i in range(a+1): for j in range(b+1): for k in range(c+1): if x == 500*i + 100*j + 50*k: ans += 1 print(ans)
実行時間が短い回答は以下です.$A,B,C,X$が50の倍数なので,50で割った値で考えています.最小通貨が1円となり,わかりやすいですね.
処理は,大きい通貨から枚数を決めていき,途中で合計金額が$X$を超えた時点でループを抜けるようになっています.全パターンを考えない分早いということですね.
また,入力が複数ある場合,ループ処理できれいに書けることがわかりました.
A,B,C,X = [int(input()) for i in range(4)] X //= 50 ans = 0 for i in range(A + 1): if 10*i > X: break rem = X - 10*i for j in range(B + 1): if 2*j > rem: break if rem - 2*j <= C: ans += 1 print(ans)
ABC083B - Some Sums
&N~A~B
\end{aligned}
n, a, b = map(int, input().split()) ans = 0 for i in range(1,n+1): s = sum(map(int, list(str(i)))) if a <= s and s <= b: ans += i print(ans)
この問題に関しては,実行時間を短くしようとすると,長いコードになるようです...
ABC088B - Card Game for Two
&N \\
&a_{1}~a_{2}~a_{3}\cdots ~a_{N}
\end{aligned}
n = int(input()) a = list(map(int, input().split())) a.sort(reverse=True) sum1 = 0 sum2 = 0 for i in range(n): if i%2 == 0: sum1 += a[i] else: sum2 += a[i] print(sum1-sum2)
ABC085B - Kagami Mochi
&N \\
&d_{1} \\
&\vdots \\
&d_{N}
\end{aligned}
n = int(input()) d = set([int(input()) for i in range(n)]) print(len(d))
他の回答も似た感じでした.
ABC085C - Otoshidama
&N~Y
\end{aligned}
\begin{cases}
\, Y=10000x + 5000y + 1000z \\
\, N=x+y+z
\end{cases}
\end{aligned}
n, total = map(int, input().split()) flag = False for i in range(n+1): for j in range(n-i+1): if 0 == 9*i + 4*j + n - total/1000: flag = True print(str(i)+' '+str(j)+' '+str(n-i-j)) break if flag: break if flag == False: print('-1 -1 -1')
この問題の実行時間が短い回答では,次が参考になります.$z$を消去するところまでは同じですが,ループの数が1つ少なくて済んでいます.注目すべき点は以下です.
- $x=(Y/1000-N-4y)/9$は整数だから,$(Y/1000-N-4y)$は$9$で割り切れる必要がある.
- 上の関係式から$(x,y)$の組が定まるが,複数候補があるなら,最も小さいものが$z=N-x-y \geq 0 $という制約条件を満たす可能性がある.よって,for b in range(9)で十分(bが小さい方から探索すれば同じこと).
def solve(N, Y): # 10000 * a + 5000 * b + 1000 * c = Y # a + b + c = N # 0 <= a, b, c # 10000 * a + 5000 * b + 1000 * (N - a - b) = Y # 9000 * a + 4000 * b = Y - 1000 * N # 9 * a + 4 * b = Y / 1000 - N # a = ((Y / 1000 - N) - 4 * b) / 9 t = Y // 1000 - N for b in range(9): if (t - 4 * b) % 9 == 0: a = (t - 4 * b) // 9 c = N - a - b if a < 0 or b < 0 or c < 0: return -1, -1, -1 return a, b, c N, Y = [int(x) for x in input().split()] print(*solve(N, Y))
ABC049C - 白昼夢
&S
\end{aligned}
s = input() list = ['dream', 'dreamer', 'erase', 'eraser'] while True: s_prev = s for c in list: if s[-len(c):] == c: s = s[:len(s)-len(c)] if s == s_prev: break if len(s) == 0: print('YES') else: print('NO')
実行時間が短い回答は以下です.どわー,なるほど,これで済むのか.
s=input().replace("eraser","").replace("erase","").replace("dreamer","").replace("dream","") print("YES" if len(s)==0 else "NO")
len(s)==0ではなく,s==""で判定している回答もありました.
ABC086C - Traveling
&N \\
&t_{1}~x_{1}~y_{1} \\
&t_{2}~x_{2}~y_{2} \\
&\vdots \\
&t_{N}~x_{N}~y_{N}
\end{aligned}
&\bigl(t+1, x(t+1), y(t+1)\bigr) \\
&=
\begin{cases}
\, \bigl(t, x(t)\pm 1,y(t)\bigr) \\
\, \bigl(t, x(t),y(t)\pm 1\bigr)
\end{cases}
\end{aligned}
- 時間ステップ差が偶数なら,偶数回移動する.よって,$x$方向と$y$方向の移動距離を足すと偶数になる.
- 同様に,時間ステップ差が奇数なら,$x$方向と$y$方向の移動距離を足すと奇数.
- 最大で移動できる距離=時間ステップ差.これより短い点は,到達後に他の点を行ったり来たりすれば到達できる(時間ステップと移動距離の偶奇性を満たす限り).
n = int(input()) start = [0, 0, 0] flag = False for _ in range(n): end = list(map(int, input().split())) diff = [end[i]-start[i] for i in range(3)] dist = abs(diff[1]) + abs(diff[2]) if diff[0]%2 == dist%2: if dist <= diff[0]: start = end else: flag = True break else: flag = True break if flag == True: print('No') else: print('Yes')
終わりに
全ての提出で「正解」のものから,参考になるコードを引っ張ってきましたが,そのコードを提出すると,追加ケースで不正解になる場合があるようです.コードを参考にする際は注意が必要ですね.