AtCoder Beginner Contest 242のきろく
AtCoder Beginner Contest 242に参加。
- A - T-shirt (100点)
- B - Minimize Ordering (200点)
- C - 1111gal password (300点)
- D - ABC Transform (400点)
- E - (∀x∀) (500点)
- F - Black and White Rooks (500点)
- G - Range Pairing Query (600点、実行時間制限: 5 sec)
- Ex - Random Painting (600点、実行時間制限: 3 sec): 未提出
- 結果、感想
A - T-shirt (100点)
の時は必ずTシャツは貰えるので、答えの確率は 、 の時は、Tシャツをもらえることが無いので です。
その他のときは 人の中から一様に 人を選ぶとき、自分が選ばれるときの確率ですので が答えとなります。
B - Minimize Ordering (200点)
内の文字を昇順に並び替えればいいので、sort
関数で並び替えてやればいいです。
C - 1111gal password (300点)
桁DPです。
とします。このとき、初期条件をとして、遷移条件によって まで でDPの値を求めたときの、 が答えとなります。D - ABC Transform (400点)
この問題では文字列を0-based indexで考えます。
A
→B
→C
→A
という循環を考えます。
から が作られるとき、 の 文字目から の 文字目と 文字目が作られます。このとき、 文字目は循環において つ進んだ文字、 文字目は循環において つ進んだ文字となります。
このことから次のことが分かります。
- の 文字目は大本を辿ると の 文字目に由来する。
→ クエリ""について 、 として、 の 文字目を求める問題として読み替えることができます。 - 元の 文字目から 回操作後の 文字目に遷移するまで、 の遷移を 回、 の遷移を 回行う。ここでの は二進数表記での である桁の数を表す函数
→ 循環上では だけ進んだ文字になります。
よってこの二つの観察から答えを導くことができました。
E - (∀x∀) (500点)
回文であるので先頭 文字の決め方について考えます。
まず、 の先頭 文字よりも辞書順で小さい 文字の文字列の数を求めます。
先頭 文字が等しいものは 個あります。ここでの は文字 のアルファベット順の順番から を引いたものです。よって を から までを足し合わせたものがここでの値です。
次に、 と先頭 文字が等しい 文字の回文が よりも辞書順で小さいかどうかを調べます。これで を定義します。この段落での最初の文での条件を満たせるなら 、そうでなければ を返します。
これらよりこの問題の答えは となります。
F - Black and White Rooks (500点)
包除原理が思いつかなかった... 通したら追記します。 upsolveしたので追記します。
白と黒の飛車/Rookが同一列、同一行内に存在するとき、その行または列内で、互いに利いている白と黒のペアが存在します。その為、各行、列は駒なし/白/黒のいずれかです。よって、各行、列の状態について、各色が選ばれた行、列の全てに駒が存在し、かつ選ばれた行、列以外に駒が存在しないような配列の方法数が分かればいい、ということまではコンテスト中には分かっていました。
選ばれた行、列のみ注目します。「いずれの行、列にも駒が存在する」ということはde Morganの法則から包除原理で計算することができます。このことから最終的な答えは です。括弧の中をメモ化しておくことで計算量 で答えることができました。
G - Range Pairing Query (600点、実行時間制限: 5 sec)
Mo’s Algorithm(莫のアルゴリズム、平方根分割)だと気づくのが遅く実装できませんでした... 通したら追記します。 upsolveしたので追記します。
各クエリに対する答えは です。区間を から や に更新するとき、追加または削除された色の人数の偶奇によって、答えが 増減したり、変わらなかったりします(具体的には人数増加して偶数になったら 、人数減少して奇数になったら 、その他は不変)。そのため、各色の人数と答えを変数で管理することで区間の の更新は で行うことができるため、Mo’s Algorithmを適用することができます。
Mo’s Algorithmはクエリを先読みし、ある特定の順番でクエリを処理することでクエリの更新回数を減らすというアルゴリズムです。全体区間をある大きさのブロックに分割し、各区間を左端がどのブロックに属すかで、ソートします。同一ブロック内の区間たちについては右端でソートします(こちらはブロックではなくもとの値でソート)。このときのブロックの大きさは大体 ぐらいにすることが多く、そのとき計算量は となります。
Ex - Random Painting (600点、実行時間制限: 3 sec): 未提出
難しそう...