1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AtCoder Beginner Contest 200(京セラプログラミングコンテスト2021)のABC問題をPythonで解答

Last updated at Posted at 2021-05-08

久しぶりにAtCoderコンテストに参加したので、自分が書いたPythonのコードを共有します。
Atcoderの解答は基本C++の解答コードが掲載され、Pythonの解答コードはないので、参考になれば幸いです。
残念ながら、解くことができたのはABC問題で、DやE、Fまでは解けていません。

A - Century

問題設定

問題文:西暦N年は何世紀ですか?
入力:西暦N年のNを標準入力
出力:何世紀が整数で出力
問題URL

ABC200のA問題のPythonの解答コード

N = int(input())
N = int((N - 1)/100) +1;
print(N)

##ABC200のA問題のPythonの解答コード解説
1行目で西暦N年を整数としてint型で標準入力し、変数Nに格納
2行目で何世紀か計算
3行目で出力

西暦N年から何世紀か計算する問題。
つまづきポイントは1世紀=西暦1年~西暦100年までという点。
単純に100で割るだけだと、西暦100年や西暦200年が次の世紀にカウントされてしまうため、先に1引くことで対処している

B - 200th ABC-200

問題設定

問題文:整数Nが与えられます。以下の操作をK回行った後の整数Nを出力してください。

  • 整数Nが200の倍数であれば、Nを200で割る。
  • そうでなければ、整数NをNの後ろに文字列として200を付け加えた整数に置き換える。

入力:整数Nと整数Kを入力
出力:問題に記載された操作を行った後の整数Nを出力
問題URL

ABC200のB問題のPythonの解答コード

N,K = map(int,input().split())
for i in range(K):
    if N % 200 == 0 :
        N = int(N /200)
    else :
        N = N *1000 + 200
print (N)

##ABC200のB問題のPythonの解答コード解説
1行目で整数Nと整数Kを入力。mapを使った入力
2行目でKの回数forループを実行
3,4行目で200で割り切れる(200の倍数)の場合は200で割る
5,6行目で200の倍数でない場合に数字の末尾に200加える
7行目で操作した結果を出力

問題の記載された通りの操作を実装。
除算をすると、整数が小数点を含むようになるため、int型に変換処理を施しておく。
200の倍数でない場合に、末尾に200足す処理は、整数Nを1000倍し、200足せばOK。

C - Ringo's Favorite Numbers 2

##問題設定

問題文:200という整数が大好きなりんごさんのために、次の問題を解いてください。N個の正整数からなる数列Aが与えられるので、以下の条件をすべて満たす整数の組(i,j)の個数を求めてください。

Ai − Ajは 200の倍数である。

入力:数列数Nと数列Aを入力
出力:問題に記載された条件を満たす個数を整数で出力
問題URL

※C問題から計算量を考慮しないといけなくなります。そのまま条件通りに解を求めても、TLEになってしまいます。

##ABC200のC問題のPythonの解答コード(TLE解答)

N = int(input())
A = [int(e) for e in input().split()]
count = 0
for i in range(N):
    for j in range(i+1,N):
        if (A[i]- A[j])%200 == 0:
            count = count + 1
print(count)

##ABC200のC問題のPythonの解答コード解説(TLE解答)

問題文の通りにコードを実装した結果、計算量がO(N^2)になってしまい、TLE出力してしまいます。

##ABC200のC問題のPythonの解答コード(正答)

N = int(input())
A = [int(e) for e in input().split()]
B = [0 for i in range(200)]
count = 0
for i in range(N):
    B[A[i]%200] = B[A[i]%200] + 1
for i in range(200):
    count = int(count + B[i]*(B[i]-1)/2)
print(count)

##ABC200のC問題のPythonの解答コード解説(正答)
計算量を少なくするために発想の転換が求められます。
条件である「(Ai-Aj)が200の倍数になる」をどう読み替えられるかが試される問題です。
上記条件は「Ai(mod 200)とAj(mod 200)が等しい」という形に置き換えられます。

例) 「201と601は余りがともに1」→601-201=400で200の倍数

数列すべてに対し、200で割った余りを求め、余りの個数が同じになったものを数えます。
200で割った余りなので、0~199までの200個のどれかに分類されます。
0-199の余り200パターンをforループで処理し、余りの個数Xから2組の数列のペアを抽出します。
X個ある中から2つ取り出す場合の数の計算の計算はxC2となるため、X(X-1)/2で計算します。
この方法であれば、計算量はO(N)となるため、TLE解答のO(N^2)よりも短時間で計算でき、時間内に解答を導くことができます。

#終わりに
ここまでC問題を解説したものの、実は時間内にC問題は解けていません(汗)
計算量O(N^2)でTLEに陥ることには気づいたものの、「Ai(mod 200)とAj(mod 200)が等しい」に読み替えることができませんでした。
解答を読んで、場合の数まで出てきたことにアハ体験を受けたので、自分なりの理解をまとめてみました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?