こんにちは, Shinoryoです.
今回はトヨタ自動車プログラミングコンテスト2023#1(AtCoder Beginner Contest 298)を, Pythonで解いてみた結果を書き連ねていこうと思います.
TOYOTA MOTOR CORPORATION Programming Contest 2023#1 (AtCoder Beginner Contest 298) - AtCoder
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
目次[非表示]
A - Job Interview
面接官の評価「良」の数を
# 入力 | |
N = int(input()) | |
S = input() | |
# 良、可、不可の数を調査 | |
ryou = sum(1 for s in S if s == "o") | |
fuka = sum(1 for s in S if s == "x") | |
# 出力 | |
if ryou >= 1 and fuka == 0: | |
print("Yes") | |
else: | |
print("No") |
B - Coloring Matrix
行列
- 行列
- 行列
を反時計回りに 回転させたもの - 行列
を反時計回りに 回転させたもの - 行列
を反時計回りに 回転させたもの
したがって, 上記4つの行列と行列
Pythonでは2次元配列の回転は, numpy
のnp.rot90
を用いることで簡単に実装できます. また,
import numpy as np | |
# 入力 | |
N = int(input()) | |
A = np.array([list(map(int, input().split())) for _ in range(N)]) | |
B = np.array([list(map(int, input().split())) for _ in range(N)]) | |
# 0~3回回転させて、「Aが1ならばBが1」が成り立つか確認 | |
# BからA_rotを引いたものに-1が含まれていれば、「Aが1なのにBが0」ということ(以外ありえない) | |
for l in range(4): | |
if np.min(B - A) >= 0: | |
print("Yes") | |
exit(0) | |
A = np.rot90(A) | |
print("No") |
配列の回転を愚直に実装することもできます.
# N×Nの配列list2Dを反時計回りに90度回転させる関数 | |
def list2D_rot90(list2D, N): | |
rot90_list2D = [[0] * N for _ in range(N)] | |
for i in range(N): | |
for j in range(N): | |
rot90_list2D[N - j - 1][i] = list2D[i][j] | |
return rot90_list2D | |
# 入力 | |
N = int(input()) | |
A = [list(map(int, input().split())) for _ in range(N)] | |
B = [list(map(int, input().split())) for _ in range(N)] | |
# 0~3回回転させて、「Aが1ならばBが1」が成り立つか確認 | |
# BからA_rotを引いたものに-1が含まれていれば、「Aが1なのにBが0」ということ(以外ありえない) | |
for l in range(4): | |
ok = True | |
for i in range(N): | |
for j in range(N): | |
if B[i][j] - A[i][j] < 0: | |
ok = False | |
if ok: | |
print("Yes") | |
exit(0) | |
A = list2D_rot90(A, N) | |
print("No") |
C - Cards Query Problem
実装手法自体はシンプルです. 配列
- クエリ
に を格納する. に が含まれていなければ, に を格納する.
- クエリ
を昇順にソートしたものを出力する.
- クエリ
を昇順にソートしたものを出力する.
# 入力 | |
N = int(input()) | |
Q = int(input()) | |
# N個の箱の用意 | |
box = [[] for _ in range(N + 1)] | |
# ある番号が格納されている箱の数を格納 | |
card = [[] for _ in range(200000 + 1)] | |
# クエリの処理 | |
for i in range(Q): | |
query = list(map(int, input().split())) | |
if query[0] == 1: | |
box[query[2]].append(query[1]) | |
if query[2] not in card[query[1]]: | |
card[query[1]].append(query[2]) | |
elif query[0] == 2: | |
print(" ".join(list(map(str, sorted(box[query[1]]))))) | |
else: | |
print(" ".join(list(map(str, sorted(card[query[1]]))))) |
クエリ
import bisect | |
# 入力 | |
N = int(input()) | |
Q = int(input()) | |
# N個の箱の用意 | |
box = [[] for _ in range(N + 1)] | |
# ある番号が格納されている箱の数を格納 | |
card = [[] for _ in range(200000 + 1)] | |
# クエリの処理 | |
for i in range(Q): | |
query = list(map(int, input().split())) | |
if query[0] == 1: | |
bisect.insort_left(box[query[2]], query[1]) | |
if query[2] not in card[query[1]]: | |
bisect.insort_left(card[query[1]], query[2]) | |
elif query[0] == 2: | |
print(" ".join(list(map(str, box[query[1]])))) | |
else: | |
print(" ".join(list(map(str, card[query[1]])))) |
D - Writing a Numeral
基本的には, 各クエリの処理に対して忠実になればよいです. 以下, 文字列[1,2,3,4,5]
, 12345
のようになります).
- クエリ
の末尾に を追加
- クエリ
の要素数を取得し, これを とする の先頭の要素を削除し, これを とする
- クエリ
を出力する
- 配列
は先頭または末尾にしかアクセスしないので,collections
モジュールのdeque
型を用いるとよい. を求める際に, これがあまりにも大きくなってしまうので, で割った余りにしてとよい. これを効率よく求めるために, Pythonの組み込み関数のpow()
を用いることができる.
from collections import deque | |
# 入力 | |
Q = int(input()) | |
S = deque([1]) | |
ans = 1 | |
mod = 998244353 | |
# 各クエリを順に処理する | |
for _ in range(Q): | |
query = list(map(int, input().split())) | |
if query[0] == 1: | |
S.append(query[1]) | |
ans = (ans * 10 + query[1]) % mod | |
elif query[0] == 2: | |
ans = (ans - pow(10, len(S) - 1, mod) * S.popleft()) % mod | |
else: | |
print(ans) |
なぜpow()
の方が速いのか?
pow()
の方が速いのは, 繰り返し2乗法と呼ばれる方法が実装されているからです. 例えば,
のようにしてしまうと, 指数を
のよう計算することができます. このようにすることで, 指数を
E以降
E以降は私の能力不足故に省略いたします.
参考にしたサイト等
- 「解説 - トヨタ自動車プログラミングコンテスト2023#1(AtCoder Beginner Contest 298)」
Editorial - TOYOTA MOTOR CORPORATION Programming Contest 2023#1 (AtCoder Beginner Contest 298)
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
- nkmk様による「Pythonのdequeでキュー, スタック, デック(両端キュー)を扱う」
Pythonのdequeでキュー, スタック, デック(両端キュー)を扱う | note.nkmk.me
Pythonの標準ライブラリcollectionsモジュールのdeque型を使うと, データをキューやスタック, デック(両端キュー)として効率的に扱うことができる. collections.deque --- コンテナデータ型 — Python 3.7.3 ドキュメント 組み込みのリストlistをキューやスタック, デック(両端キュー)として使うことも可能だが, リスト...
- nkmk様による「Pythonで指数関数・対数関数を計算(exp, log, log10, log2)」
Pythonで指数関数・対数関数を計算(exp, log, log10, log2) | note.nkmk.me
Pythonの数学関数の標準モジュールmathを使うと, 指数関数および対数関数(自然対数, 常用対数, 二進対数)の計算ができる. 9.2. math — 数学関数 指数関数と対数関数 — Python 3.6.4 ドキュメント ここでは, 自然対数の底(ネイピア数): math.e べき乗: **演算子, pow(), math.pow() 平方根(ルート): math.sqrt() 指...
- 「繰り返し2乗法, 行列累乗」
繰り返し2乗法, 行列累乗 - Qiita
繰り返し2乗法 繰り返し2乗法とは, 指数を2の累乗の積に分解し, 計算を効率化するテクニック. 例えば,
が与えられたとき, と表せるため, $3^{50} = 3^{2^{...
0 件のコメント:
コメントを投稿 (Please feel free to ask me about your questions! You can use Japanese or English in the comments.)