Codeforces Round #698 (Div. 2) 1478C - Nezzar and Symmetric Array
問題
を、個の相異なる整数からなり、任意のに対してとなる要素が存在する配列とする。
配列から生成した配列が与えられる。
ここで、である。
元の配列は存在するだろうか。
解法
Editorial of Codeforces Round #698 (Div.1, Div.2) - Codeforces
Editorialを軸に説明を進める。
前提
つまり、に相異なる個の整数が2つずつ含まれていない場合、答えはNO。
この事実から、一般性を失わず、
かつ、任意のに対して
かつ、任意のに対して
と仮定する。
式変形
前提より、において、
差分をとると、
つまり、がで割り切れない場合、答えはNO。
確認
ならば、より、において。
また、においてからが求まるので、
つまり、が0以下であるかの倍数ではない場合、答えはNO。
コード(Rust)
Submission #109130082 - Codeforces
感想
Editorialを読んでも理解できなかったため、記事を書いてみた。
少しは苦手意識を克服できた気がする。
ARC104 C - Fair Elevator
問題
解法
まず、各階に、乗った階が指定されている場合はを、降りた階が指定されている場合はをマークする(、は階数と被らない何かしらの数)。 ただし、どちらも指定されている場合は、乗った階に降りた階をマークする。 このとき、以下の場合はNoとなる。
- 同じ階が指定されている。
- 乗った階より降りた階の方が下にある。
次に、下の階から順に、乗り降りした階を対応させていく。 現在の階をとし、対応する可能性のある階をとすると、であり、この範囲を全探索すれば良い。
ここで、とを対応させた場合、とすると、において、とは制約上対応しなければならない。 つまり、これらが対応できる場合、次に探索するのは階からとなる。 ただし、以下の場合はとを対応することはできない。
- (と対応する階がない)。
- に降りた階がマークされているが、である。
- にがマークされている。
- にや降りた階がマークされている。
- に、にがマークされている(異なる人物の記録は対応できない)。
最後に、ある対応付けが上手くいった場合はYesである。 上手くいかなかった場合は、探索開始が同じであれば結果は同じとなるので、メモしておく。 よって、動的計画法の考え方に帰着された。 計算量は(恐らく)である。
コード
Submission #17181371 - AtCoder Regular Contest 104
感想
場合分けが多いと厳しい。
ABC161 D - Lunlun Number
問題
https://atcoder.jp/contests/abc161/tasks/abc161_d
番目のルンルン数を求めよ。
解法
今のルンルン数から次のルンルン数を求める方法を考える。
ルンルン数をある程度列挙して眺めてみると、繰り上がりが起きた桁は、一つ上位の桁より1小さい(0の場合は0)となっていることがわかる。
このことから、繰り上がりが起きない桁を見つければ良い。
この桁は、下位桁から順に、1を足した値が制約を満たしているかを確認していけばわかる。
あとは、その桁より下位の桁を、1を引いた値(0の場合は0)にしていけば良い。
計算量は、K番目のルンルン数をとすると、である。
コード
https://atcoder.jp/contests/abc161/submissions/16055536
一言
考察が逐次更新に偏ってしまい、全列挙に辿り着かなかった。
(ACできたので結果オーライではあるが)
yukicoder No.1170 Never Want to Walk
問題
https://yukicoder.me/problems/no/1170
座標がである個の駅がある。のとき、駅と駅に無向辺が張られている。各駅が含まれる連結成分の数を求めよ。
解法
座標が小さい順に見ていく。
Union-Findを用いて、各駅における、からの間に存在する駅を(二分探索等で列挙し)uniteすることで、で求めることができるが、これだとTLEしてしまう。
そこで、尺取り法を用いる。
具体的には、一つ前の駅において最後に辺が張られた駅(無ければ自分自身)を保存しておき、そこから探索を始める。
そうすることで、一つ前の駅と範囲が被っている部分は、最後に辺が張られた駅がuniteされることでカバーされるため、重複部分を探索する必要がなくなり、おおよそで求めることができる。
コード
https://yukicoder.me/submissions/530719
一言
尺取り法楽しい。
Codeforces 1391D 505
問題
https://codeforces.com/problemset/problem/1391/D
行列の01行列において、全ての部分偶数長正方行列に含まれる1の数を奇数にするための最小操作回数を求めよ。
解法
とする(そうでない場合はを転置)。
の場合、部分偶数長正方行列は存在しないため。
の場合、の偶奇を決めてしまえば後の列の偶奇は自然に定まるため、2通り試す。
偶奇の状態は、00 or 11、01 or 11であり、どの調整も1回の操作で済む。
の場合、との偶奇を決めてしまえば後の列の偶奇は自然に定まるため、4通り試す。
偶奇の状態は、000 or 111、001 or 110、010 or 101、011 or 100であり、どの調整も1回の操作で済む。
の場合、の正方行列が必ず含まれ、それに含まれる4つのの正方行列とそれ自身は同時に条件を満たすことができないので。
コード
https://codeforces.com/contest/1391/submission/89863543
一言
自力ACではないが、久しぶりに書いてみたくなったので書いた。
ABC147 E - Balanced Path
問題
コード
Submission #14018954 - AtCoder Beginner Contest 147
解法
左上のマスから右下のマスまで移動した際に、通ったマスに書かれている2つの数の差の絶対値を足すか引くかした値の絶対値をとすると、の最小値を求めたい。
これは、マスまでにの値をにすることができるかというbool値をとして管理すれば求めることができる。
遷移としては、がtrueの場合、次のマス( または )は、次のマスに書かれている2つの数の差の絶対値をとすると、、、のときtrueとなる。
計算量は、
感想
安定の解説ACではあるが、競プロへのモチベが微妙なので諦め。
Rust勉強中のため、コードは冗長かもしれない。
ABC136 D - Gathering Children
問題
解法
回の移動後は必ずRLとなっている箇所に集まるので(それ以外では明らかにループしない)、その箇所に集まる人数を求めれば良い。
あるRLとなっている箇所における左側のRの個数をとすると、は偶数であることから、人が左に集まり、人が右に集まる。
このことは、一番Lに近いRの位置に居た人が偶数回動くと元の位置に戻ってくることを考えるとわかりやすい。
右側のLの個数についても同じようなことが言えるが、集まる位置が左右逆になるので注意が必要である。
との求め方としては、がRの左端とすると、がRの右端、がLの左端、がLの左端となることを考えると、実装が楽になる。
コード
Submission #12485674 - AtCoder Beginner Contest 136
感想
綺麗に実装出来たので気持ちよかった。