ABCの3完!ペナ量産回!フハハハ!!
でも、klu大学さんのおかげで緑パフォでたよありがとう…!!!たなぼた!!!!
A問題
問題概要
P円のドリンク飲みたい!
- 方法その1:単品購入 P円
- 方法その2:セット購入 Q円 + 料理の値段(セットにする料理はN種類の中から1つ自由に選べる)
いっちゃん安い方法で飲みたい!
考察
- P円(単品) と Q円 + 料理リストの中でいちばん安い値段 (セット)の小さい方を出力しよう
コード
# 入力 n, p, q = map(int, input().split()) a = list(map(int, input().split())) # セット価格 set_p = q + min(a) # 単品とセット価格を比べ、安い方を出力 print(min(p, set_p))
感想
本番は慌てて変なコード書いたけど、方針はいっしょ
シンプルに考えよう、シンプルに…(念)
B問題
問題概要
商品Aに対しての、上位互換商品Bがあるか調べたいよ
定義は3つあるよ
- 商品Aと商品Bの値段を比べたとき、商品Bは同価格または安い
- 商品Aにある機能を、商品Bは全て持っている
- 商品Aより商品Bは安い、または、商品Aより商品Bは機能が多い
考察
- 制約がN≦100なので、O(N2) = 104 で、二重ループの全探索が余裕!
- 配列内を上手に分割してあげよう
- 条件②については、部分集合(AはBの一部か)を判定してあげよう
コード
# 入力 n, m = map(int, input().split()) g = [list(map(int, input().split())) for _ in range(n)] for a in range(n): for b in range(n): price_a = g[a][0] # 商品Aの値段 price_b = g[b][0] # 商品Bの値段 func_a = g[a][1] # 商品Aの機能数 func_b = g[b][1] # 商品Bの機能数 func_a_set = set(g[a][2:]) # 商品Aの機能の種類 func_b_set = set(g[b][2:]) # 商品Bの機能の種類 # 条件① 商品Aと商品Bの値段を比べたとき、商品Bは同価格または安い if price_a >= price_b: # 条件②商品Aにある機能を、商品Bは全て持っている(部分集合判定) if func_a_set.issubset(func_b_set): # 条件③商品Aより商品Bは安い、または、商品Aより商品Bは機能が多い if func_a < func_b or price_a > price_b: # 全て当てはまったら即座にYesで終了 exit(print('Yes')) # 当てはまるものがなかったらNo print('No')
感想
公式解説、たしかにすごかった!すごかった!!
なので、わたしは分かりやすさ重視で書いてみた!!!
あれ、M、使わなかったな…
C問題
問題概要
N個の文字列が入っている、配列Aがあるよ。
abc
と、反転した cba
は同じ種類と見做すよ。
文字列は、何種類ある?
考察
a
,ab
,ba
の3つの文字列がある場合、答えは2
種類になる
他の文字列と比較して解く
- 配列Aから、同じ種類のものを判定し、引く作戦
- カウント用変数
cnt
を用意 - 各文字列について、反転したものと同じものがAの中にあるかつ、反転したものが自分自身ではない場合、
cnt += 1
a
は、反転したもの(a
)と同じものがAの中にある、かつ、反転したもの(a
)が自分自身なので、カウントしないab
は、反転したもの(ba
)と同じものがAの中にある(ba
) かつ、反転したもの(ba
)が自分自身(ab
)ではないので、カウントを+1するba
は、反転したもの(ab
)と同じものがAの中にある(ab
) かつ、反転したもの(ab
)が自分自身(ba
)ではないので、カウントを+1する
- 重複でカウントするため、
cnt
をわる2する - 配列Aの長さから
cnt
を引き算
バグらせ狂ったので、本番はACしたけど、他の方法を学ぶどん!
正規化して解く
- 正規化とは:データを扱いやすいようにしてあげること!主に重複削除のことを指す
- 今回『どんな文字列』が何種類ある?とは問われていないので、文字列自体はどうでもいい(?!)
ab
ab
ba
は同じとみなすので、全て辞書昇順(または降順)で揃えab
ab
ab
に揃えたら、かんたんに重複を削除できる!ab
と、反転したba
を比較して、大きい方(または小さい方)を、setに入れてあげれば重複削除ができる!!(すごい)
コード 他の文字列と比較
# 入力 n = int(input()) # setで入力して、普通の重複は削除しておく a = set(input() for _ in range(n)) # 種類数(この時点で、反転は別種類と判断している) ans = len(a) cnt = 0 for i in a: # iを反転したものがaの中にあるかつ、iを反転したものとiが不一致なら if i[::-1] in a and i[::-1] != i: cnt += 1 # 重複削除 cnt //= 2 print(ans - cnt)
コード 正規化
# 入力 n = int(input()) a = [input() for _ in range(n)] # 答え格納用set 重複は自動的に削除される c = set() for i in a: # aの中の各iについて # 自分自身と、反転したものを比較。大きい方をcへ入れる c.add(max(i, i[::-1])) # cの要素数を出力 print(len(c))
感想
正規表現と正規化を勘違いしてたので、ついでに両方学んだ!
用語を知るだけじゃなくて、理解するができてよかったあ
DとEはわたしにはまだはやすぎた腐ってやがる!になるので、あきらめた!!またね!!!
来週のburiodenは
女子大生とおいしいパンケーキして、お昼寝したあとに、ABCやるぞお!!うおおおおおお!!!!!!