AtCoder APG4bをPythonで解く(Ex19~21)

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

Atcoder Python

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

こんにちは, Shinoryoです.

今回はC++入門 AtCoder Programming Guide for beginners(APG4b)を, Pythonで無理やり解いてみた結果を書き連ねていこうと思います.

EX19 - 九九の採点

前提として, 「Pythonでは関数への引数は全て参照渡しされます」が, 「変数の型によって, 関数内で受けた変更が関数外で保存されるかどうかが変わります」.

  • mutable型:関数内で受けた変更が関数外で保存される型. list, set ,dict等.
  • immutable型:関数内で受けた変更が関数外で保存されない型. int, float, str, tuple等.

この問題では, 関数内で受けた変更が関数外で保存されるmutable型を使うことによって, 記述することを考えます. 問題文でのプログラムと異なり, int型の変数「correct_count」「wrong_count」をまとめてリストにすることによって, プログラムを完成させることができます.

def saiten(a, correct_wrong_count):
for i in range(9):
for j in range(9):
if a[i][j] != (i+1)*(j+1):
a[i][j] = (i+1)*(j+1)
correct_wrong_count[1] += 1
else:
correct_wrong_count[0] += 1
a = [[int(x) for x in input().split()] for _ in range(9)]
correct_wrong_count = [0, 0]
saiten(a, correct_wrong_count)
for i in range(9):
for j in range(9):
if j < 8:
print(a[i][j], end=" ")
else:
print(a[i][j])
print(correct_wrong_count[0])
print(correct_wrong_count[1])

EX20 - 報告書の枚数

問題にあるプログラムをPythonで書き直すと以下のようになるでしょうか.

def count_report_num(children, x):
# プログラムをここに書く
n = int(input())
# 各組織の親組織を示す配列 0番組織の親組織は存在しないので-1を入れておく
p = [-1] + [int(x) for x in input().split()]
# 組織の関係から2次元配列を作る
children = [[] for _ in range(n)] # ある組織の子組織の番号一覧
for i in range(1,n):
children[p[i]] += [i] # parentの子組織一覧にi番を追加
#各組織について, 答えを出力
for i in range(n):
print(count_report_num(children, i))

「count_report_num(children, x)」は, 組織番号xの子組織一覧children[x]をもとに, 提出する報告書の枚数を計算する関数です.

  • 組織番号xの子組織が存在しない場合, その組織が提出する報告書は, 1枚となる.
  • 組織番号xの子組織が存在する場合, その組織が提出する報告書は, それらの子組織が提出する報告書の合計+1枚(その組織自体の分)となる.

再帰関数を利用して報告書の枚数を求めます.

def count_report_num(children, x):
if len(children[x]) == 0:
return 1
sum = 0
for j in children[x]:
sum += count_report_num(children, j)
sum += 1
return sum
n = int(input())
# 各組織の親組織を示す配列 0番組織の親組織は存在しないので-1を入れておく
p = [-1] + [int(x) for x in input().split()]
# 組織の関係から2次元配列を作る
children = [[] for _ in range(n)] # ある組織の子組織の番号一覧
for i in range(1,n):
children[p[i]] += [i] # parentの子組織一覧にi番を追加
#各組織について, 答えを出力
for i in range(n):
print(count_report_num(children, i))

EX21 - 計算量の見積もり

問題にあるプログラムをPythonで書き直すと以下のようになるでしょうか.

def f0(n):
return 1
def f1(n,m):
s = 0
for i in range(n):
s += 1
for i in range(m):
s += 1
return s
def f2(n):
s = 0
for i in range(n):
t = n
cnt = 0
while(t > 0):
cnt += 1
t /= 2
s += cnt
return s
def f3(n):
s = 0
for i in range(3):
for j in range(3):
s += 1
return s
def f4(n):
s = 0
for i in range(n):
for j in range(n):
s += i+j
return s
def f5(n,m):
s = 0
for i in range(n):
for j in range(m):
s += i+j
return s
n,m = [int(x) for x in input().split()]
a0 = -1
a1 = -1
a2 = -1
a3 = -1
a4 = -1
a5 = -1
a0 = f0(n)
a1 = f1(n,m)
a2 = f2(n)
a3 = f3(n)
a4 = f4(n)
a5 = f5(n,m)
print("f0:{}".format(a0))
print("f1:{}".format(a1))
print("f2:{}".format(a2))
print("f3:{}".format(a3))
print("f4:{}".format(a4))
print("f5:{}".format(a5))

各関数における時間計算量は, 次のように計算されます.

  • f0:O(1)(O(0)? あまりよく分かっていないです)
  • f1:O(N+M)
  • f2:O(N2/2)
  • f3:O(1)
  • f4:O(N2)
  • f5:O(NM)

ゆえに, 消すべきは「a4 = f4(n)」になります. しかし, Pythonでは計算が重いからかTLEになってしまいました.

参考にしたサイト等

関連記事

Search

About Me

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

Labels

Blog Archives