Panasonic Programming Contest (AtCoder Beginner Contest 186)をPythonで解く

投稿日:  更新日:2022/09/02

Atcoder Python

B!
Daniel AgreloによるPixabay(https://pixabay.com/)からの画像

こんにちは, Shinoryoです.

今回はPanasonic Programming Contest (AtCoder Beginner Contest 186)を, Pythonで解いてみた結果を書き連ねていこうと思います.

A - Brick

NWで割った商を出力すればよいです.

# 入力
N, W = [int(x) for x in input().split()]
# 出力
print(N // W)

B - Blocks on Grid

2次元配列Aの最小値を求め, 2次元配列Aの各成分からその最小値を差し引いた残差を全て足し合わせればよいです.

下の例では, 多次元リストを1次元に平坦化するためにitertools.chain.from_iterable()を用いています. 単に2次元配列をmin()の引数にとるだけでは, list型の和になってしまいます.

import itertools
# 入力
H, W = [int(x) for x in input().split()]
Amatrix = [[int(x) for x in input().split()] for _ in range(H)]
# Amatrixの最小値を求める
# itertools.chain.from_iterableで1次元化
minA = min(itertools.chain.from_iterable(Amatrix))
# 各々のマスで取り除くべきブロックの数を計算する
Amatrix_remain = [[Amatrix[i][j] - minA for j in range(W)] for i in range(H)]
# Amatrix_remainの合計を求める
# itertools.chain.from_iterableで1次元化
print(sum(itertools.chain.from_iterable(Amatrix_remain)))

C - Unlucky 7

Pythonには数値を8進数の文字列に変換できる関数oct()があるので, それをありがたく使わせていただこうと思います.

# 入力
N = int(input())
# 答えの格納
ans = 0
# 7チェック
for i in range(1, N+1):
if ("7" not in str(i)) and ("7" not in oct(i)):
ans += 1
# 答えを出力
print(ans)

oct()を使わないのだとすれば, 定義に則って10進数を8進数に変換することになります. 関数化した方が楽だと思います.

# 8進数に変換する関数(int型を受け取ってstr型を返す)
def to_oct(n):
# 8進数に変換した文字列を記録していく
s = ""
while(n):
# 下の位から順に8で割った余りを計算していく
s = str(n % 8) + s
n //= 8
return s
# 入力
N = int(input())
# 答えの格納
ans = 0
# 7チェック
for i in range(1, N+1):
if ("7" not in str(i)) and ("7" not in to_oct(i)):
ans += 1
# 答えを出力
print(ans)

D - Sum of difference

この結果はA1,,ANの順序に依存しないので, ソートして並べ替えてしまってよいです. A1ANとすれば, |AiAj|=AjAiになります.

まずぱっと思いつくのは, 律儀に全パターン計算する方法です. しかし, この方法だとO(N2)となり, TLE.

# 入力
N = int(input())
A = sorted([int(x) for x in input().split()])
# 答えを格納する変数
ans = 0
# 全場合を足していく
for i in range(N-1):
for j in range(i+1,N):
ans += A[j] - A[i]
# 答えを出力
print(ans)

そこで, 若干工夫をします. 求めるのは

(1)i=1N1j=i+1N|AiAj|

ですが, A1ANとできることを利用すれば,

i=1N1j=i+1N|AiAj|=i=1N1j=i+1N(AjAi)=i=1N1(j=i+1NAjAij=i+1N)(2)=i=1N1(j=i+1NAj(Ni)Ai)

となります. j=i+1NAjはあらかじめ累積和をO(N)で求めておくことで対応できます. これを用いることで, (ソートでかかる時間計算量を考慮して)O(NlogN)でできます.

# 入力
N = int(input())
A = sorted([int(x) for x in input().split()])
# 答えを格納する変数
ans = 0
# Aの累積和を格納する配列
Aruiseki = [[] for _ in range(N)]
# Aの累積和を計算しておく
Aruiseki[N-1] = A[N-1]
for i in range(N-2,-1,-1):
Aruiseki[i] = Aruiseki[i+1] + A[i]
# Aの累積和を利用して計算する
# 配列のindexに注意
for i in range(N-1):
ans += Aruiseki[i+1] - (N - i - 1) * A[i]
# 答えを出力
print(ans)

E以降

E以降は私の能力不足故に省略いたします.

参考にしたサイト等

Search

About Me

自分の写真
理系大学生でした. Bloggerを利用して発信を行っています.

Labels

Blog Archives