🤯
競技プログラミング:考察の種
AtCoder/Codeforcesのアルゴリズムコンテスト向けに、時々見返して持ち球を忘れないようにするためのページです
随時更新しています。
一覧
前提
何においてもまず誤読に気を付ける
一見悪い計算量の方針
盲点になりやすい
- 単に制約が小さい(よく見よう)
- グラフや配列は大きいけど
とか書いてあって1\leq K\leq10 などになるO(KN\log N) - 超頂点、
ごとにデータ構造を作る、距離K まで探索などK
- 超頂点、
- グラフや配列は大きいけど
- 見た目ほど計算量が悪くない
- 計算量は悪いけど高速化できる
- 操作が反転やpopcountで表せるならbitsetを疑う ABC348F
- 平方分割で計算量が悪いケースを避けられる
- パラメータが小さい時だけ使える解法と大きい時だけ使える解法がある ABC335F
- 要素は多いけど要素が持つ値や状態のバリエーションが少ない
具体例- 32bit非負数列
の累積OR/累積AND 端を固定したとき出現する値は高々32通りA - 値0~9の出現回数の偶奇(1024通り) ABC295D
- 32bit非負数列
ペアの典型
他に考察ステップがあると見えづらくなったり途方に暮れたりする
- 2次元平面上の座標
と見なす(x,y) - 平面走査と合わせて"
が小さくx が大きいもの"とか"長方形の面積"に帰着 ABC346Gy
- 平面走査と合わせて"
- 辺と見なす
- 頂点と見なす
- 普通に超頂点を作ってBFSとかで最短経路求めるやつ ABC394E
そもそもペアを見出す部分に発想がいるものの例
操作列の典型
順番がどれくらい重要かで系統が分かれる
- 順番が関係ないとき
- (選ぶ問題のとき)何らかの基準でソートして良いものから選ぶ
- 計算しやすい順番に並べ替える → Mo
- 順番は関係あるが、後で決めても良いとき
- 順番が関係あるとき
- 操作の影響範囲を変更する
- 範囲に対する操作を境界に対する操作に言い換える
簡単なところで区間加算→imos、部分木の根に作用→DFSなど 遅延伝搬も同じ発想 - 対象への操作を、全体への操作+対象以外への逆操作に言い換える ABC398D
- 範囲に対する操作を境界に対する操作に言い換える
- 操作を分解する
- 結果が以前の操作に依存しなければ、後ろから見る
-
番目以前とi-1 番目以後の干渉を気にしなくても良いなら、i+1 番目で区切る(区間DPみたいにするも良し、順方向の結果と逆方向の結果を繋いでも良し)i
- 操作の影響範囲を変更する
- 操作が多すぎるとき
求値の典型
まとめたい
DPの典型
まとめたい
- 求値の典型と同じく、求めるものを言い換える
- 要素についての走査→要素が取る値についての走査
num\sum_{i\in S} f(i) = \sum_{v} v\times (i\in S | f(i)=v)
- 要素についての走査→要素が取る値についての走査
- 切れ目を全部試す
- 戻すDP ABC321F
整数の典型
- 桁が大きすぎる場合、何らかの値でmodを取って代表させる
- 個別の値に興味がない場合: 状態をまとめてDPをする
- 個別の値に興味がある場合: 複数の素数の組合せで確率的に一致させる ABC339F
グラフ化の典型
明示的にグラフと言われていないものをグラフとして解く
他の典型と重複しまくり
- 順列:巡回置換ごとに考える
- 周期の最小公倍数 回移動すれば、どの点から出発しても必ず元の位置に戻る
- 大小関係:小さい要素
大きな要素への有向辺を張る\rightarrow - 大小関係を満たすようにできるか?はDAGになっているか?と言い換えられるABC277F
- ペアの典型で書いたもの
- 高度典型で書いたもの(2-SAT、フローに帰着)
適宜追加
簡略化の典型
ABCの中ではad-hoc感があるもの
- 一見複雑な形状だが矩形で考えても良い ABC347F
- 隣り合った要素だけに注目しても良い ABC404E
忘れやすい事実
- 約数の数(少ない)
までなら10^9 個以下、1,344 までなら10^{18} 個以下103,680 - 素数の数(多い)
までなら10^9 個以下 素数定理50,847,534 \pi(x) \approx x/\ln(x)
→ 競プロで扱うレンジの数に対しては1桁落ちる程度 - 素因数の種類数(めちゃくちゃ少ない)
までなら8種類以下、10^9 までなら15種類以下参考10^{18}
個数切り詰めて使う場面がありそう - その他、良い感じの大きさになるパラメータ
-
分割数
でn=50 204,226 - 階乗(順列全列挙)
9!=362,880 - 組合せ
C_{20} _{10}=184,756
-
分割数
- 0は平方数 ABC324D
- 単純パスの列挙は
O(N!) - 二項係数を全部足すと
、奇数番目or偶数番目だけなら2^n 2^{n-1} - 写像十二相は考えるよりカンペを見た方が早い
-
二部グラフであるもの: 木、矩形グリッド(三次元でも)など 「奇閉路を持たない」とも表現される
- ハニカムグリッドは二部グラフではない
- 「立方体グラフ」はグラフ理論の用語で、現実の立方体とはちょっと違う
- グラフの次数に関する性質
- 「○○の定理」の類
- 達成するまでにかかる回数の期待値
1回以上かかる確率= 2回以上かかる確率+ ...+
高度典型
解けなくても困らない場面は多いが、時々刺されて泣きを見る
- 畳み込み ABC392G
形式的べき級数の考え方と相性が良い
値を次数、出現回数を係数とした多項式を作る→多項式の積が全組合せの通り数になる
としたとき、\sum_{i}n_{i}x^i \times \sum_{i}m_{i}x^i = \sum_{i}k_{i}x^i -
は1つ目の式と2つ目の式から値(次数)を1つずつ選んだ和がk_{i} になるような選び方の総数i -
で、k_{i}=\sum_{j\in [0,i]}n_{i-j}m_{j} とn の畳み込みになっているm
-
-
フロー
- ABC239G ABC320G
- 特に、燃やす埋める(Project Selection)と呼ばれるもの ABC326G ABC347G ABC193F 典型90 040
一般に表せるのは一点の割当に対して報酬/コスト、二点の割当が異なる時のコスト(これを使って" を選ぶにはa を選ばないといけない"を表せる)b
一般には解けないけど追加の制約があれば解けるパターンを知っておく- 二点の割当が同じ時のコスト
→ どちらかの頂点の意味を反転させればOK(反転させるものとさせないものが二部グラフなら使える) - 3点以上の関係に関するコスト
→ 1つ以上が ならコスト、全てc なら報酬、の形ならOKc
複数頂点への制約を表す超頂点を作るのは典型?
- 二点の割当が同じ時のコスト
- Dinic法の時間計算量は押さえ方が色々あり、制約次第で意外と小さくなる
辺数 、最大流|E| に対しF や、二部マッチングで頂点数O(F|E|) に対し|V| などO(\sqrt{|V|}|E|)
の成分は必ずかかる(当たり前)|E|
-
文字列系(そんな高度扱いじゃないかも)
- 加工してからz-algorithmやSA-ISなどをやる
- 反転
- 連結
- その際にダミー文字を挿入(元の文字列@反転文字列, a@b@c@dなど)
Suffix Arrayなどで共通部分列を出したりできる
- その際にダミー文字を挿入(元の文字列@反転文字列, a@b@c@dなど)
- substringを1つの文字列として扱う
- ただ殴れる
- Aho-Corasick ABC362G ABC268Ex
- Palindromic tree(EERTRRE) math314のブログ ABC398F
- 似たようなやつの一覧
- z-algorithm: 各iを始点とする先頭との最長共通部分列
- KMP: 各iを終端文字とする先頭との最長共通部分列
- Manacher: 各iを中心とする最長回文
- EERTREE: 各iを終点とする最長回文
- suffix array: 各iを始点とする接尾辞を辞書順ソートしたもの
- 考え方?
- 接頭辞と見たらTrie, Rolling-Hash, z-algorithmなど色々思い浮かべてみて楽なものを選ぶ
- 沢山連結するのは名前付きアルゴリズムよりDPを疑う
- 加工してからz-algorithmやSA-ISなどをやる
-
最小シュタイナー木問題 出所はだいたいこれ
bitDP解法は性質上、ターミナル {任意の1点}を連結させる時の最小コストが求まる ABC364G ABC395G\cup - 並列二分探索 ABC394G ABC233G
- 2-SAT
でSCC分解、とだけ覚えると使えない 必ず乗法標準形a \Rightarrow b を作ってクロージャ(a \lor b) \land (c \lor d)... をa \lor b に変換する\lnot a \Rightarrow b \land \lnot b \Rightarrow a - 離散対数問題
modx^k \equiv y や、m 型の問題はBaby step giant stepを疑う ABC270f^N(x)=y - 高難易度木問題を解くテクニック集
- 有理数の二分探索はStern-Brocot木 ABC333G 提出
軽めの典型問題
で悩まないようにしたい
- 最長パスはトポロジカルソートの要領
- 最短閉路は辺を決め打って削除→最短経路、全点対最短経路→往路+復路など
何となく見えた方針に囚われない
-
ABC417D よく見る「区間
だけ通過できるやつ」の亜種と思って境界を考えようとすると駄目[L_i, R_i)
その他 未分類
- 乱択 心の片隅に置いておく ABC339F ABC422E
- インタラクティブ
- 約数系包除で混乱する時はメビウスの反転公式から出発する ABC304Fでの応用
のときF(n) = \sum_{d|n}f(d)
f(n) = \sum_{d|n}\mu(\frac{n}{d})F(d) -
個のA,n 個のB,m 個のCの並べ方であって全てのAは全てのBの左側にあるものの通り数ABC405Ek - 連結した文字の辞書順 ABC225F
-
でソートして考える(これは全順序で、比較関数として機能する)S+T<T+S - 前から連結すると壊れる(大小関係が今まで作った文字列の長さに依存)ので後ろから連結する(新しく連結する文字列の長さのみに依存)
-
- 斜め累積和 ABC265F
- 超有名問題を一部改変しただけ、は元の超有名問題の解法に気を取られると良くない ABC408E
その他 思考の癖に気付く
典型を当てはめるだけ、組み合わせるだけ、と言われることでも自分には降って湧いたように見える場合がある
- パスを扱う木DPをする時、個別のパスに注目する → パスの本数でまとめるDPに気付けない
- bitDPをする時、TSPや順列のイメージから出発する → 要素番号の昇順に見る遷移ABC352Fに気付けない
- どでかい素数は陽に求めないと決め付ける → 区間篩に気付けない
Discussion