Python3で解いた AtCoderの勉強になった問題 2020
- サマリー
- AtCoder Beginner Contest
- 169 C-Multiplication 3 (2020-05-31)
- 169 D - Div Game (2020-05-31)
- 170 D - Not Divisible (2020-06-14)
- 172 C - Tsundoku (2020-06-27)
- 172 D - Sum of Divisors (2020-06-27)
- 173 C - H and V (2020-07-05)
- 174 C - Repsept (2020-08-02)
- 176 D - Wizard in Maze (2020-08-22)
- 178 C - Ubiquity (2020-09-13)
- 180 C - Cream puff (2020-11-01)
- 181 D - Hachi (2020-10-17)
- 182 D - Wandering (2020-11-08)
- 183 D - Water Heater (2020-11-15)
- 184 D - increment of coins (2020-11-22)
- 186 D - Sum of difference (2020-12-19)
- AtCoder Regular Contest
- 最後に
- 参考書籍
サマリー
- 6月くらいから、AtCoderやってみようと、ふと思い立って初めて約半年。
- 年末時間ができたから復習していてそこで面白かった問題を上げていく。
- 基本過去記事の再掲しつつ、もう一度振り返る。
AtCoder Beginner Contest
169 C-Multiplication 3 (2020-05-31)
問題は以下 atcoder.jp 初めての参戦で、いきなりこの問題でWAを超絶だした記憶。オーバーフローや計算精度に関する問題も出るのかと痛感した。
どういう時に問題が起きるのかをそもそも理解できずに、試行錯誤しつつ、以下のうように、浮動小数は実際には正しい値を保持していないことを改めて知って勉強になった。
0.07 * 100 # 7.000000000000001 0.29 * 100 # 28.999999999999996
でもDecimalモジュール使えばいいやと思って通した。
a, b = map(str, input().split()) res = int(a) * Decimal(b) print(int(res))
けど本来は、数値をそのまま掛け合わせて後で割って整数部分だけ取得するとやってほしかったんだろうなぁ
a, b = map(str, input().split()) c,d = b.split('.') # int(c+d)とするとbを文字通り100倍された結果になる。 res = a * int(c+d) print(res//100)
169 D - Div Game (2020-05-31)
問題は以下 atcoder.jp この当時は、素因数分解をする方法もコードに落としてなくて1から実装しなきゃで大変だったが、それさえできればあと一工夫でできる。
170 D - Not Divisible (2020-06-14)
問題は以下
この当時は、エラトステネスの篩的な考えもコードに落としてないし、発想としても持っていなかった。
- リストに含まれるある値の定数倍の値をふるい落とすという考えを学んだ
- また、
in
で探すときは対象をlist
ではなくset
にしておくことが速度として重要というのも学んだ
n = int(input()) a = list(map(int, input().split())) a_s = sorted(a) a_set = set(a_s) maxv = max(a) res = [0] * (maxv+1) rep = 0 for i in a_s: # iを評価してない時はiを含むの定数倍のところは+1 if res[i] == 0: for j in range(i, maxv+1, i): res[j] += 1 # iを評価してあればiを+1 # すでに定数倍として評価されていたら2以上にしたい else: res[i] += 1 cnt = 0 # 最終的に検索対象が定数倍リスト内で1になっているものだけをカウントする for i in range(n): if res[a[i]] == 1: cnt += res[a[i]] print(cnt)
172 C - Tsundoku (2020-06-27)
問題は以下 atcoder.jp
ここらへんから記事書き始めた。
- しゃくとり
- 累積和と二分探索
この時、これらのイメージを掴んだ感じ
172 D - Sum of Divisors (2020-06-27)
問題は以下 atcoder.jp
Pythonだとでもだと通らないということを感じた回だった。
工夫すれば、
約数 等差数列の和で計算できる。
173 C - H and V (2020-07-05)
問題は以下 atcoder.jp
はじめてbitをコードで起こした。bit演算子である、'&'や '>'の意味を学んだ。
- bit全探索
- itertoolsのproduct の両者を学んだ。bitは未だに苦手でbitで全パターン検索するような場合は先にproductで作ってしまうほうが考えやすい。
174 C - Repsept (2020-08-02)
問題は以下 atcoder.jp
愚直に'7'をいくつも並べたものを順に割っていくっていうのはだめ。基本的にという様にたくさん文字列を羅列する形は遅い。
純粋に'7', '77', '777' ... なので初項7, 公比10の等比数列と考える。
- 等比数列の和
- 余りで考えれば良いのでモジュラの性質をうまく使って10倍されていく時にあまりを10倍して考えればオーバーフローなどを木にする必要がなくなる。
176 D - Wizard in Maze (2020-08-22)
問題は以下 atcoder.jp
結構重くて、なかなか通らなかった。 対策としては、外側へのはみ出しを防止。結構むずくて、今解き直しても素直に実装できなそう。
- 上下左右を'##'で埋める。
- あとは歩いていけなくなるまで普通の迷路探索 。
- ワープのパターン出いけるところに歩いていける範囲としてキューに加える。
178 C - Ubiquity (2020-09-13)
問題は以下 atcoder.jp
愚直に条件に当てはまるものを求めるのではなく、包括原理より、全パターンから条件に合わないものを引くとしたほうがいいパターン。
ポイントとして、という形は愚直に計算すると遅いので計算過程ではくり返し二乗法を使う
180 C - Cream puff (2020-11-01)
問題は以下 atcoder.jp
単純な約数列挙だが、いちからコード書くと結構大変だった。考え方としては素因数分解と同じようなイメージでいけた。からまで試し割りして、 割り切れたものと、割り切れたときの商を別々に保持して後でリストを連結
181 D - Hachi (2020-10-17)
問題は以下 atcoder.jp
単純な倍数判定だが、入れ替えを考慮するため侮れない。 結果から言うと、Counterで8の倍数の下3桁の文字列のパターンと一致するかどうかで判断。Counterの結果は引き算できることがポイント
182 D - Wandering (2020-11-08)
問題は以下 atcoder.jp
その時までの値の累積和とその時までの値の最大値の和を考える。 図示しながら考えるとわかり良い。
183 D - Water Heater (2020-11-15)
問題は以下 atcoder.jp
持ち方がポイントで、使うスケジュールの最初の時刻でプラス、終わりでマイナスしたリストを頭から順に足し合わせていくようにして、スケジュールの累積和として考える
184 D - increment of coins (2020-11-22)
問題は以下 atcoder.jp
メモ化を自動的にやってくれるlru_cacheというデコレータを知った。 メモ化と比較するとスッキリすることがわかる。
186 D - Sum of difference (2020-12-19)
問題は以下 atcoder.jp
久しぶりにコンテストの最中にDまで解けた。
引き算の絶対値がポイントで、事例を書き出して、ソートして考えても良いと考えられれば単純な数え上げとなる。
AtCoder Regular Contest
106 B - Value (2020-10-24)
問題は以下
Union-Find問題。連結しているグループの値の和が一致するかを検討するだけ。このとき注意しなくてはいけないのは、find()でrootを求めていく。
109 B - log (2020-11-28)
問題は以下
これまで、リストが存在する二分探索はやったことがあったが、この問題ではリストを作ってから行うと、TLEとなってしまうため、midの値を適切に変形し 探索したい値と比較する。
110 B - many (2020-12-05)
問題は以下
最初'0'にアサインできたら、最後、左から数えて何番目の'0'にアサインできるかを考える問題
最後に
結局だいたい実際にコンテストで解いた問題全部あげただけみたいになってしまったがまとめながら、半日かけて、ここに書き出した問題をもう一度解き直しして良い復習ができた。
ブログにまとめながらやっていたおかげで数ヶ月前に書いたコードを少し見直しただけで思い出せたし、復習が比較的楽にできてよかった。
2020年06月以前の問題も実際には精進として解いていて、その中でも良さげな問題はあったが、とりあえず今回は取り扱わないでおいた。
参考書籍
けんちょんさんの本。非常に参考になる。行き詰まった時にもう一度読み直したりしてる。
こちらで、書籍を7章まで進めている。