Ruteのプログラミング日記

競技プログラミング(AtCoder)の問題の解説や、過去問を解いた感想、また解けない過去問について共有したいと思ってます。

AtCoder Beginner Contest 161 感想&反省[For Beginners]

AtCoder Beginner Contest 161 が2020/04/04に行われました。みなさんお疲れ様でしたー。

今回はA,B,C問題を3完。Performanceも668と、茶色パフォーマンスでした。

 

解説

A問題

https://atcoder.jp/contests/abc161/tasks/abc161_a

いろいろな解法があります。

時間のかかる解法になりますが、3つの数字をリスト(配列)と捉え、問題文通りに実装すればよさそうです。

  1. A = list(map(int,input().split()))
  2. A[0],A[1] = A[1],A[0]
  3. A[0],A[2] = A[2],A[0]
  4. print(*A)
  5. #豆知識 (*リスト名)とすると、リストの
  6. 要素を全て出力することが出来ます

B問題

https://atcoder.jp/contests/abc161/tasks/abc161_b

問題文通り実装すればよさそうです。

  1. N,M = map(int,input().split())
  2. A = list(map(int,input().split()))
  3. B = sum(A)*(1/(4*M))
  4. ans = 0
  5. for i in range(N):
  6. if A[i]>=B:
  7. ans += 1
  8. if ans >= M:
  9. print("Yes")
  10. else:
  11. print("No")

 

C問題

https://atcoder.jp/contests/abc161/tasks/abc161_c

数学の問題です。始めに、

  1.  N = K
  2.  N < K
  3.  N > K

の3つのパターンでそれぞれどうするかを考えます。

1.N = Kの場合

N - Kをすると、絶対値は0になり、その後は0→K→0→Kを繰り返すので

0を出力しましょう。

2.N < Kの場合

例えば、N = 3,K = 7の場合。4→3→4→3 \dotsとなり、

N = 2,K = 6の場合、4→2→4→2 \dotsとなります。

つまり、abs(N-K)Nの最小値といえそうです。

ただし、これには例外があり、 2N<Kの場合は、Nが最小値となります。

3. N > Kの場合

N = 7, K = 3の場合 4→1→2→1 \dots

N = 11, K = 3の場合8→5→2→1→2 \dots

となります。つまり、K-(N \% K)Nの最小値といえそうです。

ただし、場合によっては N \% KNの最小値となる場合があるので

min(K-(N \% K),N \% K)を出力すればどちらのケースでも対応できます。

あとはこれを実装すればよいです。

  1. N,K = map(int,input().split())
  2. if N==K:
  3. print(0)
  4. elif N > K:
  5. if N%K == 0:
  6. print(0)
  7. else:
  8. print(min(N%K,K-(N%K)))
  9. elif N < K:
  10. if 2*N<K:
  11. print(N)
  12. else:
  13. print(abs(N-K))

 

D問題はどう見ても数学っぽいので飛ばしました。

 

E問題

https://atcoder.jp/contests/abc161/tasks/abc161_e

この問題、解けそうな感じがしたのでTryしてみました(解説ではありません)

まずは、テストケースを見てみます。

入力例 1 Copy

Copy
11 3 2
ooxxxoxxxoo ooxxxoxxxoo

出力例 1 Copy

Copy
6

高橋君は 11 日間のうち 3 日働こうとしています。ある日働いたらその後 2 日間は働きません。

働く日としてありえる組み合わせは「1,6,10 日目」「1,6,11 日目」「2,6,10 日目」「2,6,11 日目」の 4 通りです。

したがって、6 日目に必ず働きます。

ここで考えたのは、"x"の数の累積和を利用して解くというものです。

(Sのi文字目をS[i]とします)

ooxxxoxxxoo という文字列があった時に、S[i]までの"x"の文字列の数をそれぞれ計算していきます。

すると、[0,0,1,2,3,3,4,5,6,6,6]という配列が完成しました。

働ける日の条件として

1日働いたらC日は働かない

"x"の書いてある日付では働かない

という条件であるので

S[i]からS[i+C]番目の文字列で

・S[i] = "o"である

・S[i]からS[i+C]までの文字列に含まれる"o"の個数が1個以上ある

という条件に当てはまる日が働ける日の候補 ということで考えてみました。

それからいろいろと実装をしていきました。

すると、なんとサンプルケースに当てはまっていくではありませんか!

提出をしてみたのですがWA。理由が今でもよく分かっていませんorz

  1. N,K,C = map(int,input().split())
  2. S = input()
  3. L = [0]*(N)
  4. ans = 0
  5. P =
  6. for i in range(N):
  7. if S[i] == "x":
  8. ans += 1
  9. L[i] = ans
  10. for i in range(C):
  11. L.append(ans)
  12. Q =
  13. for i in range(N):
  14. flag = 0
  15. if S[i] == "o":
  16. #もし1日目で働ける場合
  17. if L[i+C]-L[i] <= C:
  18. #累積の休み日数がC以下
  19. P.append(i+1)
  20. else:
  21. if len(P) >= 1:
  22. s = P.copy()
  23. Q.append(s)
  24. P.clear()
  25. else:
  26. if len(P) >= 1:
  27. s = P.copy()
  28. Q.append(s)
  29. P.clear()
  30. Q.append(P)
  31. if len(Q) == K:
  32. for i in range(len(Q)):
  33. if len(Q[i]) == 1:
  34. print(*Q[i])

以上、A問題~C問題の解説と、E問題の考察でした。

今回を含め、以降の記事ではPython3で書いたコードをここにまとめることにします。

(Githubでも良かったのですがブログ上に貼り付ける方が便利なので)

 

ちなみに、今日21:00から行われる Judge System Update Test Contest 202004は、

unratedのコンテストです。(順位表から、4問なので おそらく旧ABC級?)

も し か す る と First Accepted (FA)を取れる機会にもなりそうなので、FA取りたい人は1番を目指して頑張って下さい!

(ペナルティはつきますがratedでは無いので関係ないと思います)