2023-07-03

AtCoder Beginner Contest 308に参加した

競プロアルゴAtCoder

ABC308の参加記.

7月1日に開催されたCodeQUEEN 2023 予選 (AtCoder Beginner Contest 308)に参加した.結果はABCDEFの6完,提出するのが遅く水パフォで1125位だった.

A - New Scheme

問題文

8個の整数S1,,S8S_1, \cdots, S_8が与えられ,特定の条件を満たすかどうかを判定する問題.

やるだけだが,「すべてのiiについてSiS_iが条件PPを満たす」かどうかを判定するよりも「SiS_iが条件PPを満たさないようなiiが存在する」かどうかを判定するほうが実装が楽.

提出:https://atcoder.jp/contests/abc308/submissions/43087977

B - Default Price

問題文

皿の色ごとに値段が決まっている料理をNN個食べたとき,合計金額を求める問題.色をキーにして値段をDictionary型で保持すればよいが,価格リストにない色が来た場合ときだけ注意が必要.

提出:https://atcoder.jp/contests/abc308/submissions/43090499

C - Standings

問題文

1,,N1, \cdots, NPiAi/(Ai+Bi)P_i\equiv A_i/(A_i+B_i)の降順でソートする問題.PiP_iの値を小数でじかに持つと誤差の関係で落ちるので,まじめに比較関数を書いてやる必要がある.

落ちるだろうなーと思いながらとりあえず提出してペナを出すのをやめたい.

提出:https://atcoder.jp/contests/abc308/submissions/43099789

D - Snuke Maze

問題文

英小文字が書かれたH×WH\times Wのグリッドがあり,"snuke"という文字列をたどるようにして左上から右下まで到達できるかを判定する問題.

隣のマスに遷移できるかどうかは「隣のマスに書かれている文字」のほかに「"snuke"の何文字目まで読んだか」で決まるので,「現在いるマス」と「"snuke"の何文字目まで読んだか」を状態に持ってBFSすればよい.

提出:https://atcoder.jp/contests/abc308/submissions/43107522

E - MEX

問題文

面白かった!

0,1,20,1,2からなる長さNNの数列AAと,M, E, Xのみからなる長さNNの文字列SSが与えられるので,

i<j<k(SiSjSk="MEX")mex(Ai,Aj,Ak)\sum_{\substack{i<j<k\\ (S_iS_jS_k="{\rm MEX}")}}{\rm mex}(A_i, A_j, A_k)

を求める問題.

よく考えると,mex{\rm mex}の値は0,1,2,30,1,2,344通りしかない.だから,mex{\rm mex}の値ごとに,その値が何回加算されるかが分かればよい(いわゆる「主客転倒」というテクニック).

例えば,mex(Ai,Aj,Ak)=1{\rm mex}(A_i, A_j, A_k)=1になるのはどういうときかというと

とき.だから,mex(Ai,Aj,Ak)=1{\rm mex}(A_i, A_j, A_k)=1となるような組(i,j,k)(i, j, k)の個数を求めるには

が分かればよく,これは

という形のDPで求められる(kkはbitDPの容量で2進数でもつ).

mex{\rm mex}の値が他の値になる場合についても,このDPテーブルの値を使えば求められるので,全体としてO(N)O(N)で解くことができた.

提出:https://atcoder.jp/contests/abc308/submissions/43115620

F - Vouchers

問題文

こういう感じの,貪欲をひねり出す問題が苦手.

NN個の商品があり,商品iiの定価はPiP_iと決まっている.実はMM枚のクーポンを持っており,クーポンjjをある商品に適用すると,その商品がDjD_j円引きになる.ただし,クーポンjjは定価LjL_j円以上の商品にしか使用できないし,クーポンと商品の対応は単射でないといけない.このとき,うまくクーポンを使ってNN個の商品を買うときの合計金額を最小化せよ,というのがこの問題の主旨.

クーポンに適用可能な定価の下限があるのがやっかいだ.

ひとまずこの制限がない場合を考えると,明らかに値引き額の大きいクーポンから順に使っていくのが最適である.また,最終的に使うクーポンの集合が同じであれば,どのクーポンをどの商品に使っても同じ(最終的な合計額のみが問題だから).

次に制限がある場合を考える.この場合には,どのクーポンをどの商品に使うかが重要になってくる.定価の高い商品ほど,適用可能なクーポンの選択肢が減ることに気づくと,以下のような貪欲が回るように思える.

実際にこれは正しい(本番では正当性を証明せずに提出したが,ユーザ解説などに詳しい説明がある).

実装する際には,まだクーポンを使用していない商品の集合を管理し,その都度,ある値以上の最小の要素を取得する必要がある.Pythonにはmultiset上の二分探索どころかmultisetすらないので,慣れないC++を書く羽目になりかなり時間を取られた.

提出:https://atcoder.jp/contests/abc308/submissions/43141628