ホーム
/
作ったもの
/
考えたこと
/
きろく

競プロ頻出数値表・公式集 / Tips集

計算量見積もり・計算量削減

頻繁に用いる数値のサイズの見積もりや、畳み込みなどの公式を集めておきました。

数値表

計算量見積もりやデータ型の限界(オーバーフロー)確認に便利な概算表です。

計算量(オーダー)の具体値目安

\(N\) の制約 オーダー 概算計算量 (具体値) 頻出するアルゴリズム・処理
\(1.2 \times 10^6\) \(O(N \log N)\) 約 \(2.4 \times 10^7\) (高速でない)ゼータ変換
\(2 \times 10^5\) \(O(N (\log N)^2)\) 約 \(6.2 \times 10^7\) サボったときのセグメント木上の二分探索、マージソート木
\(2 \times 10^5\) \(O(N \sqrt{N})\) 約 \(8.9 \times 10^7\) Mo's algorithm、平方分割
\(10^7\) \(O(N \log \log N)\) 約 \(4.5 \times 10^7\) エラトステネスの篩
\(2.0\times 10^3\) \(O(N^2\log N)\) 約 \(4.3 \times 10^7\) RSK対応
2000 \(O(N^3 / 64)\) 約 \(1.25 \times 10^8\) bitsetを用いた定数倍高速化
15 \(O(3^N)\) 約 \(1.4 \times 10^7\) 部分集合の部分集合の列挙 (Submask DP)
40 \(O(2^{N/2})\) 約 \(1.0 \times 10^6\) 半分全列挙 (Meet-in-the-middle)
3000 \(O(N^2 \log N)\) 約 \(1.0 \times 10^8\) \(O(N^2)\) のループ内で二分探索や優先度付きキューを使用
11 \(O(N!)\) 約 \(3.9 \times 10^7\) 順列全探索 (next_permutation)

2の累乗 \(2^n\)

\(n\) 正確な値 概算
10 1,024 \(1.02 \times 10^3\)
15 32,768 \(3.28 \times 10^4\)
20 1,048,576 \(1.05 \times 10^6\)
25 33,554,432 \(3.36 \times 10^7\)
30 1,073,741,824 \(1.07 \times 10^9\)
31 2,147,483,648 \(2.15 \times 10^9\)
40 1,099,511,627,776 \(1.10 \times 10^{12}\)
50 1,125,899,906,842,624 \(1.13 \times 10^{15}\)
60 1,152,921,504,606,846,976 \(1.15 \times 10^{18}\)
63 9,223,372,036,854,775,808 \(9.22 \times 10^{18}\)

※ \(2^{31}-1\) は32bit符号付き整数(int)の最大値、\(2^{63}-1\) は64bit符号付き整数(long long)の最大値です。

フィボナッチ数 \(F_n\)

\(n\) 正確な値 概算
10 55 \(5.50 \times 10^1\)
20 6,765 \(6.76 \times 10^3\)
30 832,040 \(8.32 \times 10^5\)
40 102,334,155 \(1.02 \times 10^8\)
45 1,134,903,170 \(1.13 \times 10^9\)
50 12,586,269,025 \(1.26 \times 10^{10}\)
60 1,548,008,755,920 \(1.55 \times 10^{12}\)
70 190,392,490,709,135 \(1.90 \times 10^{14}\)
80 23,416,728,348,467,685 \(2.34 \times 10^{16}\)
90 2,880,067,194,370,816,120 \(2.88 \times 10^{18}\)

※ \(F_{45}\) 付近で32bit上限を、\(F_{92}\) 付近で64bit上限を超えます。

二項係数 \({}_{2n}\mathrm{C}_n\)

\(n\) 正確な値 概算
10 184,756 \(1.85 \times 10^5\)
15 155,117,520 \(1.55 \times 10^8\)
20 137,846,528,820 \(1.38 \times 10^{11}\)
25 126,410,606,437,752 \(1.26 \times 10^{14}\)
30 118,264,581,564,861,424 \(1.18 \times 10^{17}\)
33 7,219,315,550,148,874,272 \(7.22 \times 10^{18}\)

※ 中央の二項係数は最も大きくなります。\(n=33\) (\({}_{66}\mathrm{C}_{33}\)) で64bit上限に近づきます。

階乗 \(n!\)

\(n\) 正確な値 概算
5 120 \(1.20 \times 10^2\)
8 40,320 \(4.03 \times 10^4\)
10 3,628,800 \(3.63 \times 10^6\)
12 479,001,600 \(4.79 \times 10^8\)
15 1,307,674,368,000 \(1.31 \times 10^{12}\)
20 2,432,902,008,176,640,000 \(2.43 \times 10^{18}\)

※ 順列の全探索 \(O(N!)\) が現実的なのは \(N=10 \sim 11\) 程度までです。

ベル数 \(B_n\)

\(n\) 正確な値 概算
4 15 \(1.50 \times 10^1\)
6 203 \(2.03 \times 10^2\)
8 4,140 \(4.14 \times 10^3\)
10 115,975 \(1.16 \times 10^5\)
12 4,213,597 \(4.21 \times 10^6\)

※ ベル数 \(B_n\) は、\(n\) 個の異なる要素からなる集合を 空でない部分集合に分割する方法の総数です。 第二種スターリング数 \(S(n,k)\) を用いて \(B_n = \sum_{k=0}^{n} S(n,k)\) と表せます。

第二種スターリング数 \(S(n,k)\)

\(n\) \(k\) 正確な値 概算
4 2 7 \(7.00 \times 10^0\)
6 3 90 \(9.00 \times 10^1\)
8 4 1,701 \(1.70 \times 10^3\)
10 5 42,525 \(4.25 \times 10^4\)
12 6 1,323,652 \(1.32 \times 10^6\)

※ 第二種スターリング数 \(S(n,k)\) は、\(n\) 個の異なる要素を、 空でない \(k\) 個の部分集合に分割する方法の総数です。 漸化式は \(S(n,k) = kS(n-1,k) + S(n-1,k-1)\) です。 初期条件は \(S(0,0)=1\) です。

\(10^n\) 以下の素数の個数 \(\pi(X)\)

\(n\) 範囲 \(X = 10^n\) 素数の個数 \(\pi(X)\)
2 100 25
3 1,000 168
4 10,000 1,229
5 100,000 9,592
6 1,000,000 78,498
7 10,000,000 664,579
8 100,000,000 5,761,455
9 1,000,000,000 50,847,534
12 1,000,000,000,000 37,607,912,018

※ エラトステネスの篩の計算量や、素因数分解の個数見積もりに役立ちます。\(10^6\) 以下の素数は約7.8万個、\(10^9\) 以下は約5000万個です。

高度合成数(約数の個数)

高度合成数 \(N\) 約数の個数 備考・主な閾値
7,560 64 \(10^4\) 以下で最多
98,280 128 \(10^5\) 以下で最多
720,720 240 \(10^6\) 以下で最多
7,351,344,000 1,344 \(10^9\) 以下で最多
9,637,611,984,000 6,720 \(10^{12}\) 以下で最多
9,979,291,666,558,4000 26,880 \(10^{18}\) 以下で最多(64bit型で約数最多)

※ 「その数未満のどの自然数よりも約数の個数が多い数」です。\(10^9\) 以下の値でも約数は高々1344個、`long long` の限界付近でも26880個にしかならないため、約数を全列挙した後の処理は非常に高速に動作します。

素数階乗 \(p\#\)

\(k\) 素数 \(p_k\) \(p_k\text{\#}\) (正確な値)
3 5 30
5 11 2,310
7 17 510,510
9 23 223,092,870
10 29 6,469,693,230
11 31 200,560,490,130
13 41 304,250,263,527,210
15 47 614,889,782,588,491,410

※ 素数階乗 \(p_k\text{\#}\) は、最初の \(k\) 個の素数の積です。異なる素因数を多く持つ数(極めて約数が多い数)の構築などに頻出します。15番目の素数(47)で64bit整数の上限に近づきます。

約数関数の総和 \(\sigma_1(N)\) の最大値目安

\(N\) の上限 \(\sigma_1(N)\) が最大となる \(N\) \(\sigma_1(N)\)
\(10^3\) 840 2,880
\(10^4\) 7,560 28,800
\(10^5\) 83,160 345,600
\(10^6\) 720,720 3,265,920

※ 約数の総和 \(\sigma_1(N)\) は、基本的には高度合成数付近で最大になります。

公式集 / Tips集

組み合わせ・二項係数

ヴァンデルモンドの畳み込み

用途: 2つのグループから合わせて選ぶ組み合わせの計算

$$ \sum_{k=0}^r \binom{m}{k}\binom{n}{r-k} = \binom{m+n}{r} $$
補足説明を開く

サイズ $m$ の集合とサイズ $n$ の集合から合わせて $r$ 個を選ぶ方法は、全体の $m+n$ 個から $r$ 個を選ぶ方法に等しいという恒等式です。計算量削減の要になることが多々あります。

ホッケースティック恒等式

用途: 二項係数の列和を一つにまとめる

$$ \sum_{k=r}^n \binom{k}{r} = \binom{n+1}{r+1} $$
補足説明を開く

パスカルの三角形において、ある列に沿って足し合わせた和が斜め下の値に等しくなる性質です。区間和を定数時間で求める際に利用します。

多項係数と二項係数

用途: 多項定理における係数の分解展開

$$ \binom{n}{k_1,k_2,\dots,k_m} = \binom{n}{k_1} \binom{n-k_1}{k_2} \cdots \binom{n-k_1-\cdots-k_{m-1}}{k_m} $$
補足説明を開く

全体からまず $k_1$ 個を選び、残りから $k_2$ 個、さらに残りから $k_3$ 個というように選んでいく過程に対応しています。

同値類の「標準形(代表元)」定義による全単射の構築

用途: 操作や回転・置換で互いに移り変わる同値な状態の重複カウントを防ぎ、数え上げやDPを可能にする

同じ構造や同値類に属する状態集合 $S$ に対し、一意な判定ルール(例:「操作手順の中で辞書順最小のもの」「ソート・正規化された状態」など)を満たす標準形(Canonical Form)を1つ定義する。 「問題の対象」と「標準形」の間に全単射を作り、標準形のみをカウント・探索対象とする。

補足説明を開く

例えば「いくつかの操作を行って到達可能な盤面の数」を求める際、盤面から逆算して「常に一意な操作(例: 最も左上の違反箇所を直す操作)のみを遡ったときに得られるルート」だけを辿ることで、探索木を重複のない木構造に変化させることができる(逆検索法 / Canonical Path)。

ゲーム理論

不偏ゲームの選択和

用途: 必勝判定

$N$ 個の不偏ゲーム $G_1,G_2,\cdots,G_N$ の選択和について、$N$ 個のゲームが全て後手必勝であれば後手必勝、そうでなければ先手必勝である。

補足説明を開く

ゲームの選択和とは、各手番で $1$ 以上 $N$ 個以下のゲームに着手するようなゲームを指す。

不偏ゲームの結合和

用途: 必勝判定

$N$ 個の不偏ゲーム $G_1, G_2, \dots, G_N$ の結合和の勝敗は、各ゲーム $G_i$ の遠隔度(Remoteness) $R(G_i)$ の最小値によって判定できる。 $\min_{1 \le i \le N} R(G_i)$ が奇数ならば先手必勝、偶数($0$ を含む)ならば後手必勝である。

補足説明を開く

ゲームの結合和(Selective Compound)とは、毎手番で $N$ 個のゲームすべてに同時に着手するゲームのことである。いずれか $1$ つ以上のゲームで手が指せなくなった(終了盤面に達した)時点で全体のゲームが終了する。

局面 $G$ の遠隔度 $R(G)$ は、互いに最適な行動をとった場合にその局面からゲームが終了するまでの残り手数を表し、以下のように再帰的に定義される:

  • $G$ が終了盤面の場合:$R(G) = 0$
  • $R(G')$ が偶数となる遷移 $G \to G'$ が存在する場合:$R(G) = 1 + \min \{ R(G') \mid G \to G', R(G') \text{ は偶数} \}$
  • $G$ が終了盤面でなく、$R(G')$ が偶数となる遷移が存在しない場合:$R(G) = 1 + \max \{ R(G') \mid G \to G' \}$

勝者(奇数手数で終わらせたい側)は最も早く終了する手を選んで最短で勝ちにいき、敗者(偶数手数にしたい側)は少しでも長引かせる手を選ぶため、最小値の遠隔度の偶奇を判定することで全体の勝敗が得られる。

不偏ゲームの皇帝和

用途: 必勝判定

$N$ 個の不偏ゲーム $G_1, G_2, \dots, G_N$ の皇帝和の勝敗は、各ゲームが後手必勝盤面($P$ 局面)であるかと、後手必勝盤面に対して定義される値 $l(G_i)$ の XOR 和(Nim-sum)によって判定できる。 すべての $G_i$ が後手必勝盤面であり、かつ $\bigoplus_{i=1}^N l(G_i) = 0$ である場合に限り後手必勝、それ以外の場合は先手必勝である。

補足説明を開く

ゲームの皇帝和(Autocratic Compound)とは、毎手番で $N$ 個のゲームのうち $1$ つを選んで $1$ 回以上連続して着手し、その他の $N-1$ 個のゲームそれぞれに対しては $0$ 回以上 $1$ 回以下着手するゲームのことである。

各後手必勝盤面 $G$ に対して定義される値 $l(G)$ は、後手必勝盤面同士の遷移における最大の長さを表し、以下のように定義される:

$$l(G) = \max \{ l(G') + 1 \mid G \to^+ G', G' \text{ は後手必勝盤面} \}$$ (上の記号は、自分一人のみで1回以上の着手によって到達可能な後手必勝盤面の全体を指す。ただし、$G$ から $1$ 回以上の着手によって到達可能な後手必勝盤面 $G'$ が存在しない場合は $l(G) = 0$ とする。)

この性質により、すべてのゲームが後手必勝盤面であるという条件下において、皇帝和は各ゲームの $l(G_i)$ を山の高さとみなした標準的な Nim に帰着される。

確率・期待値

達成するまでにかかる回数の期待値

用途: 離散確率分布における期待値の変形

$$ \text{達成するまでの回数の期待値} = \sum_{k=1}^{\infty} P(\text{達成に} k \text{回以上かかる}) $$
補足説明を開く

非負の整数値をとる確率変数 $X$ の期待値は、$E[X] = \sum_{k=1}^\infty P(X \ge k)$ と変形できます。これを活用して状態の計算を簡略化することが多々あります。

整数論・代数・演算

剰余に関する命題

用途: 素数冪を法とする剰余の分解

$p$ を素数、$x$ を非負整数とする。$r$ を $p$ と互いに素な非負整数として、$x = rp^k$ と書けるとき、以下が成り立つ:

$$x \equiv (r \text{ mod } p^e) \times p^k \pmod {p^e}$$

和と排他的論理和の関係

用途: 足し算をXORとANDに分解する

$$x + y = x \oplus y + 2 (x \land y)$$
補足説明を開く

2進数での足し算の繰り上がりを $2(x \land y)$ が担当し、繰り上がらない部分を $x \oplus y$ が担当します。条件式変形の定番です。

mexと排他的論理和の関係

用途: XORをmexとして理解する

$$x \oplus y = \text{mex }\{a \oplus y , x \oplus b \mid 0 \leq a < x , 0 \leq b < y\} $$
補足説明を開く

参照:Nimber (Nim和を和、Nim積を積とした数体系は体をなす。)

切り上げ (Ceiling) の床関数変換

用途: 整数除算での切り上げ実装

$$\left\lceil \frac{X}{M} \right\rceil = \left\lfloor \frac{X + M - 1}{M} \right\rfloor$$

四捨五入 (Round) の床関数変換

用途: 整数除算での四捨五入実装

$$\text{round}\left( \frac{X}{M} \right) = \left\lfloor \frac{2X + M}{2M} \right\rfloor$$

ある値を超過するかの判定

用途: オーバーフローの回避

$$xy > z \iff x > \left\lfloor \frac{z}{y} \right\rfloor$$

$K$ 進法における $d$ 桁目の抽出

用途: 任意の基数での特定桁の数字の取得

整数 $X$ の $K$ 進法における $d$ 桁目の数字 (0-indexed):

$$\left( \left\lfloor \frac{X}{K^d} \right\rfloor \bmod K \right) = \left\lfloor \frac{X}{K^d} \right\rfloor - K \cdot \left\lfloor \frac{X}{K^{d+1}} \right\rfloor$$

$abc = n$ なる $a,b,c$ の数え上げ

用途: nが10^7程度までなら、1 ~ n までのこの数え上げをまとめて計算できる

以下のように表すと、高速ゼータ変換2回で計算できる。

$$\#\{(a,b,c) \in \mathbb{N}^3 \mid abc = n\} = \sum_{d | n} \sum_{d' | d} 1 = \sum_{d | n} \sigma_0(d)$$

和の $k$ 乗を積に変換するテクニック

用途: 和のk乗の和を計算するときに有用

和の $k$ 乗は以下のように計算できる。この計算においては、$K$ 次以下の項のみを持てば良い。

$$(A_1 + A_2 + \cdots A_N)^K = K![x^K] \prod_{i = 1}^{N} e^{A_ix}$$
補足説明を開く

具体的な例として、「配列 $A = (A_1, A_2, \dots, A_N)$ のすべての部分集合 $S$ について、その総和の $K$ 乗を足し合わせた値」を求める問題を考えます。

直感的に書くと、求めたいのは以下の値です。 $$ \sum_{S \subseteq \{1, \dots, N\}} \left( \sum_{i \in S} A_i \right)^K $$

ここで、和の $K$ 乗を母関数の形式 $\left( \sum_{i \in S} A_i \right)^K = K! [x^K] \prod_{i \in S} e^{A_i x}$ に置き換えると、式は次のように変形できます。

$$ \begin{aligned} \sum_{S \subseteq \{1, \dots, N\}} \left( \sum_{i \in S} A_i \right)^K &= \sum_{S \subseteq \{1, \dots, N\}} \left( K! [x^K] \prod_{i \in S} e^{A_i x} \right) \\ &= K! [x^K] \sum_{S \subseteq \{1, \dots, N\}} \prod_{i \in S} e^{A_i x} \quad \text{(係数抽出 $[x^K]$ と 総和 $\textstyle\sum$ の入れ替え)} \\ &= K! [x^K] \prod_{i=1}^{N} \left( 1 + e^{A_i x} \right) \quad \text{(分配法則による因数分解)} \end{aligned} $$

なぜ計算量が劇的に減るのか:
そのまま計算すると部分集合 $2^N$ 通りそれぞれについて和の $K$ 乗を計算する必要があり、$O(2^N \cdot N)$ の時間がかかります。
しかし、変換後の式では「各要素 $i$ を選ぶ($e^{A_i x}$)か選ばない($1$)か」の $2^N$ 通りの組み合わせの和が、$\prod_{i=1}^N (1 + e^{A_i x})$ という $N$ 個の多項式の積に展開(因数分解)されています。

必要な項は $x^K$ まで($K+1$ 項分)で十分なため、各 $1 + e^{A_i x}$ を高次項を切り捨てながら掛け合わせる(分割統治や NTT などを利用する)ことで、$O(2^N)$ から多項式時間($O(N K \log N)$ など)へ大幅に高速化できます。

A mod X の不変量評価による半減解析(ならし計算量)

用途: 配列の要素に対する Mod 更新クエリ(「区間内の要素を $A_i \bmod X$ に置き換える」等)の実行回数を評価する

任意の値 $A, X$ に対し、$X \le A$ であるならば必ず $A \bmod X < \frac{A}{2}$ が成り立つ。 つまり、値が変化するような Mod 操作が適用されるたびに、その要素の値は半分未満に激減する。

補足説明を開く

$X > A$ のときは $A \bmod X = A$(不変)であり、$X \le A$ のときは $X \le \frac{A}{2}$ ならば $A \bmod X < X \le \frac{A}{2}$、$X > \frac{A}{2}$ ならば $A \bmod X = A - X < \frac{A}{2}$ となり、いずれにせよ半分未満になる。 したがって、各要素が実際に更新される回数は高々 $O(\log(\max A))$ 回である。Segment Tree などで「区間最大値 $\ge X$」の箇所のみに再帰的に走査・更新を行うことで、全体 $O((N + Q) \log N \log(\max A))$ で処理できる。

ラグランジュ補間

用途: 通る点から多項式の値を復元する

多項式 $P(x)$ が $N + 1$ 個の点 $(x_i,y_i)$ を通るときの $P$ の明示的な式。

$$P(x) = \sum_{i=0}^N y_i \prod_{j \neq i} \frac{x - x_j}{x_i - x_j}$$
補足説明を開く

特に評価点が $x = 0, 1, \dots, N$ のように連続している場合、分母が階乗の積になり、分子の累積積を前計算しておくことで、通常 $O(N^2)$ かかる補間を $O(N)$ に落とすことができます。

合成閉じ(閉包性)を持つ関数クラスの代数的パラメータ管理

用途: 複雑なクエリ操作の合成・一括適用(遅延セグメント木・ダブリングなど)をデータ構造に乗せる

関数 $f(x)$ と $g(x)$ の合成 $f(g(x))$ が、同形式の関数パラメータの更新として表現できる性質(閉包性)を利用する。 関数そのものではなく、関数を決定づけるパラメータ(係数やタプル)の合成規則を定義して管理する。

補足説明を開く

【代表例】
1. 1次変換: $f(x) = ax + b \implies f(g(x)) = a_1(a_2 x + b_2) + b_1 = (a_1 a_2)x + (a_1 b_2 + b_1)$
2. クランプ関数: $f(x) = \min(\max(x + a, b), c)$(区間加算と区間 chmin / chmax の合成)
3. アフィン変換行列: ベクトルに対する操作を行列積にまとめる
遅延セグメント木の作用素(Lazy tag)として乗せる際、この「合成に関する閉包性」を満たすことが必須要件となる。

置換・群論

互換と置換の積

用途: 置換の結合法則と操作の解析

$P$ を置換として、$P(a\ b) = (P(a)\ P(b))P$ が成り立つ。

巡回置換の共役

用途: 巡回置換を別の置換で挟んだときの変形

$P$ を置換として、$P (a_1\ a_2\ \dots\ a_k) P^{-1} = (P(a_1)\ P(a_2)\ \dots\ P(a_k))$ が成り立つ。

バーンサイドの補題

用途: 対称性を考慮した数え上げ

有限群 $G$ が集合 $X$ に作用しているとき、同値類(軌道)の個数 $|X/G|$ は、各 $g \in G$ による固定点集合を $X^g = \{ x \in X \mid g \cdot x = x \}$ として、以下が成り立つ。

$$|X/G| = \frac{1}{|G|} \sum_{g \in G} |X^g|$$

隣接スワップの最小回数と転倒数

用途: 配列Aを隣接要素の交換(swap)のみで配列Bに変換する際の、最小操作回数の導出と理解

配列Aを隣接スワップのみで配列Bに変換するために必要な最小回数は、配列Aの各要素が配列Bのどの位置に向かうべきかを対応付けた新しい数列を作り、その数列の転倒数(Inversion Number)を求めることで計算できる。 なお、AをBにする手順とBをAにする手順は対称(逆再生)であるため、AとBの役割を完全に入れ替えて計算しても同じ答えが得られる。

補足説明を開く

転倒数とはなにか?
転倒数とは、ある数列の中で「大小関係が逆転しているペアの個数」のことである。具体的には、ある数列において、$i < j$ であるにもかかわらず「$i$ 番目の要素 $> j$ 番目の要素」となっているようなインデックスの組 $(i, j)$ の総数を指す。
隣接する要素を1回スワップすると、数列全体の転倒数は必ず $+1$ または $-1$ される。目的の配列(完全にソートされた状態 = 転倒数 $0$)に到達させるためには、無駄なく $-1$ されるスワップを選び続けるのが最適であり、その結果「最初の状態の転倒数」がそのまま「必要な最小スワップ回数」となる。

その求め方は?
以下の手順で数列を変換し、その転倒数を求めることで計算できる。

  1. 位置の対応付け: 配列Bの各要素が「Bの何番目(インデックス)にあるか」を記録する。
    ※重複要素がある場合: 配列内に同じ値が複数含まれる場合、A内での1番目の $k$ とB内での1番目の $k$ を対応付けるなどする。
  2. 配列Cの作成: 配列Aの各要素を、ステップ1で求めた「向かうべきBでのインデックス」に置き換えた新しい数列 $C$ を作る。これにより、「Aの各要素が最終的にどの位置に行くべきか」を表す数列ができる。
  3. 転倒数の計算: 作成した数列 $C$ の転倒数を求める。

たとえば、$A = [2, 3, 1, 4]$、$B = [4, 1, 3, 2]$ の場合、Bの要素のインデックスは {4:0, 1:1, 3:2, 2:3} となる。Aの要素をこれに置き換えて新しい数列 $C = [3, 2, 1, 0]$ を作成し、この数列 $C$ の転倒数を計算すると $6$ となり、これが最小スワップ回数となる。

文字列

使用する文字列の集合を固定した場合の文字列結合の辞書順最小化

用途: 各文字列が1回しか使えない状況下での複数の文字列を並べ替えて結合し、辞書順最小の文字列を作る

与えられた文字列の集合を、比較関数 $S + T < T + S$ が true となる順序でソートし、その順番で結合すると辞書順最小になる。

補足説明を開く

文字列 $S$ を小数とみなせば、結局、$\frac{S}{1 - 10^{-|S|}}$ の比較となる。 これより、全順序であることが従う。

使用回数制限のない文字列結合の辞書順最小化

用途: 前からの貪欲法が成り立たない文字列連結・選択問題で辞書順最小を求める

$DP[i] =$ 「残り $i$ ステップで作れる辞書順最小の文字列」と定義し、末尾($i=1$)から順に以下のように確定させる。 $$DP[i] = \min_j \left( S_j + DP[i-1] \right)$$

補足説明を開く

前から決定すると将来選ぶ文字列によって優先度が崩れるが、後ろから確定させれば $DP[i-1]$ が定数扱いになるため、$S_j$ を先頭に付けた文字列同士を比較するだけで部分構造最適性が成り立つ。

連結順序によらない桁数と辞書順による整数比較

用途: 数字列を連結して整数を作るとき、その桁数や大小を扱う

leading zero を許した同じ桁数の整数の大小比較は、文字列としての辞書順比較と一致する。 すなわち、桁数が等しい数字列 $S,T$ について $S < T$ であることと、それらが表す整数について $\operatorname{val}(S) < \operatorname{val}(T)$ であることは同値である。

補足説明を開く

通常の整数表記では先頭の $0$ は省略するが、ここでは leading zeroを許容して桁数を固定する。 たとえば、007 と 012 はともに3桁の表現であり、 数字列としては 007 < 012、 整数としても $7 < 12$ となる。 一般に、同じ長さの数字列 $A=a_1a_2\cdots a_n$、 $B=b_1b_2\cdots b_n$ があり、 最初に $a_i \ne b_i$ となる位置が $i$ なら、 $a_i < b_i$ のとき必ず $\operatorname{val}(A) < \operatorname{val}(B)$ である。 これは $\operatorname{val}(A)-\operatorname{val}(B)$ の符号が、その最初の異なる桁によって決まるためである。

したがって、連結によって作られる文字列の長さをまず考えれば、 同じ桁数の候補については文字列の辞書順をそのまま整数の大小関係として 扱うことができる。

整合な括弧列(正しい括弧列)の実践的な同値条件・言い換え

用途: 競技プログラミングやアルゴリズム設計において、括弧列の判定・構築・数え上げ・区間クエリを、DP、セグメント木、グラフ、累積和などの扱いやすい構造に帰着させる

長さ $2N$ の「(」と「)」からなる括弧列 $S$ について、以下が同値。

補足説明を開く
  • 先頭からの割合: 任意の $1 \le i \le 2N$ において、$S_1, \dots, S_i$ のうち$\lceil i / 2 \rceil$ 個以上が「(」である。かつ、$S_1, \dots, S_{2N}$ のうちちょうど $N$ 個が「(」である。(※左から貪欲に構築する問題やDPの判定条件として頻出)
  • 末尾からの割合: 任意の $1 \le i \le 2N$ において、後ろから $i$ 文字($S_{2N-i+1}, \dots, S_{2N}$)のうち$\lceil i / 2 \rceil$ 個以上が「)」である。かつ全体の「)」が $N$ 個。(※文字列を後ろから走査する際に必須の条件)
  • 累積和の最小値 ($\pm 1$ 変換): 「(」を $+1$、「)」を $-1$ とした数列の累積和 $A$ を考えたとき、$A_{2N} = 0$ であり、かつ全ての $i$ について $A_i \ge 0$ である。(※この累積和をセグメント木に乗せることで、「括弧の反転クエリ」や「区間整合性クエリ」に $O(\log N)$ で対応可能になる基本テクニック)
  • 未マッチ括弧の縮約(隣接キャンセル): 文字列から隣り合う「()」を消去する操作を繰り返すと、最終的に空文字列になる。また、いかなる部分文字列もこの操作を限界まで行うと必ず「))))((((」のように「閉じ括弧が連続した後に開き括弧が連続する」形になる。(※部分区間の括弧列の状態をマージするモノイドとしてセグ木に乗せる際の超重要性質)
  • 非交差マッチング: 全ての「(」と「)」をペアにして結んだとき、各ペア $(u, v)$ ($u < v$) は $S_u =$「(」かつ $S_v =$「)」を満たし、さらにどの2つのペアの線も交差しない。(包含関係にあるか、完全に独立しているかのどちらかのみ。※区間スケジューリングや円環上の交差問題への帰着に有用)
  • 一意な再帰構造 (文法): $S$ は空文字列であるか、あるいはある整合な括弧列 $A, B$ を用いて「(」+ $A$ +「)」+ $B$ という形に「一意に」分解できる。(※数え上げの区間DPや、カタラン数の漸化式 $C_N = \sum(C_i \times C_{N-i-1})$ を導出する際の基本構造)
  • Dyck路(グリッド上の経路): 「(」を右 ($x+1$)、「)」を上 ($y+1$) への移動とみなしたとき、原点 $(0,0)$ から $(N,N)$ へ至る最短経路のうち、直線 $y = x$ を一度も上に超えない(常に $x \ge y$)経路である。(※鏡像法によるカタラン数の組み合わせ的計算への帰着)
  • 木のオイラーツアー(DFS軌跡): $N+1$ 頂点の順序付き根付き木において、根からDFS(深さ優先探索)を行い、「辺を下るときに ( 」「辺を上るときに ) 」と記録して得られる文字列と一対一対応する。(※木の問題を括弧列の問題に変換し、LCA(最小共通祖先)をRMQ(区間最小値クエリ)で解くための基礎)
  • 巡回シフトと最小値(Raneyの補題): 「(」と「)」が $N$ 個ずつある任意の(整合とは限らない)括弧列に対し、$\pm 1$ の累積和が最小となるインデックスの直後で巡回シフト(分割して前後を入れ替える)すると、必ず整合な括弧列になる。(※「条件を満たすように切り出して構築しろ」といったアドホックな構築問題での必殺技)

回文をDP的に扱うには

用途: 回文を扱う際のデータの持ち方

回文をDP的に扱うときには、真ん中(これは回分)を持っておいて、前と後ろに1文字ずつくっつけていくことを考えると、扱いやすくなる。

挿入と削除のみからなる編集距離

用途: レーベンシュタイン距離もどきの高速化

文字列 $S$ から挿入・削除のみを繰り返して $T$ を構築する場合の最小手数は $|S| + |T| - 2 \times |LCS|$ となる。

補足説明を開く

一般に、(連続していない)LCSについては $O(|S||T|)$ で計算できるが、$|S|$ が重複する文字を持たないような文字列の場合には $O(|S| + |T|\log |T|)$ で計算できる。

幾何

ピックの定理

用途: 格子点上の多角形の面積と格子点数の関係

頂点がすべて格子点上にある自己交差のない多角形の面積 $S$ は、内部の格子点の数を $I$、周上の格子点の数を $B$ とすると、以下が成り立つ。

$$S = I + \frac{B}{2} - 1$$

グラフ理論

DFSは辞書順に列挙

用途: 条件を満たす構造(文字列・経路・割り当てなど)のうち「辞書順最小」のものを1つ構築する

各状態からの遷移肢(子のノード)を選択する際、あらかじめ「辞書順が小さくなる順」にソートして走査するDFSを行う。 解(終点)に最初に到達した時点で探索を即座に終了(打ち切り)すれば、その解が全体における辞書順最小解となる。

補足説明を開く

DFSは「常に最も左の未探索枝」を優先して深さ方向に進むため、探索順序そのものが全体解の辞書順と完全に一致する。 DPで後続の最小値を保持して前から復元する方法に比べ、枝刈り(Pruning)と組み合わせやすく、状態や文字列の比較コストを考慮せずに $O(\text{探索頂点数})$ で解が得られる。

平面グラフにおける関係式

用途: 頂点・辺・面(サイクル)・連結成分数の計算

平面グラフにおいて、頂点数を $V$、辺数を $E$、独立なサイクルの個数(内側の面の数)を $L$、連結成分の数を $C$ とすると、以下の関係式が成り立つ:

$$C = V - E + L$$
補足説明を開く

※ サイクルが存在しない森の場合は $L = 0$ となり、$C = V - E$ が成り立ちます。木の場合はさらに $C = 1$ なので $V - E = 1$ になります。

強連結な向き付け可能性

用途:強連結な向き付けの可能性判定

橋を持たない有限連結グラフ $G$ は強連結な向き付けを持つ。

木の直径に関する性質

用途: 木の最も遠い2点(直径)の検出

木の直径の両端点を $u,v$ とすると、$u$ から最も距離が遠い頂点の一つが $v$ であり、逆も同様である。したがって、任意の頂点 $s$ から最も遠い頂点 $u$ を求め、さらに $u$ から最も遠い頂点 $v$ を求めれば、 $u,v$ は木の直径の両端点となり、

$$d(u,v)=\operatorname{diam}(T)$$

が成り立つ。この性質は、辺に非負の重みを付けた重み付き木でも、距離を辺重みの総和として定義すれば成り立つ。

補足説明を開く

【固定した頂点から最も遠い頂点】 木 $T$ の頂点 $s$ を一つ固定したとき、直径の両端点を $u,v$ とすれば、そのいずれかは $s$ から最も遠い点になります。

木の中心 (Tree Center) の定義と性質

用途: 木の同型判定、最長距離の最小化(ミニマックス施設配置)

【定義】
頂点 $v$ から最も遠い頂点までの距離を $e(v) = \max_{u \in V} d(v, u)$ としたとき、$e(v)$ が最小となる頂点を 木の中心 と呼ぶ。

【重要な性質】

  • 存在個数と位置:
    中心は必ず 1個 または 隣接する2個 のいずれか存在する。特に、木の直径をなすパスの 中点 に必ず一致する。
  • すべての直径の交差点:
    木の中に最長パス(直径)が複数存在する場合でも、すべての直径は必ず木の中心を通る(共有する)。
  • 木の同型判定への応用:
    中心は「木の構造のみ」から一意に定まるため、中心を根とした根付き木に変換することで、非根付き木の同型判定(ハッシュ比較など)を効率的かつ一意に行うことができる。
補足説明を開く(同型判定の工夫)

同型判定において中心が2つ存在する場合は、両方の頂点をそれぞれ根としてハッシュを計算し比較するか、2つの中心を結ぶ辺の中点にダミー頂点を追加して唯一の中心(根)とみなす手法がとられます。

木の重心 (Tree Centroid) の定義と性質

用途: 距離の総和の最小化、分割統治法(重心分解)

【定義】
頂点数 $N$ の木において、ある頂点 $v$ を削除したときに分かれる各連結成分(部分木)の頂点数の最大値を $s(v)$ としたとき、$s(v) \le \lfloor \frac{N}{2} \rfloor$ を満たす($s(v)$ が最小となる)頂点を 木の重心 と呼ぶ。

【重要な性質】

  • 存在個数:
    重心も中心と同様に、必ず 1個 または 隣接する2個 のいずれか存在する。重心が2個になるのは、頂点数 $N$ が偶数であり、ある辺を取り除くと正確に $N/2$ 個ずつの2つの成分に分割できる場合のみである。
  • 距離の総和の最小化と凸性:
    重心は、他のすべての頂点からの距離の総和 $\sum_{u \in V} d(v, u)$ を最小化する頂点である。また、任意の頂点から重心へ向かって移動すると、この距離の総和は単調に減少する性質がある。
  • 重心分解による $O(\log N)$ 構造:
    重心を取り除いてできる各部分木のサイズは常に元の半分以下になるため、この操作を再帰的に繰り返してできる木(重心木)の深さは必ず $O(\log N)$ となる。木上のパスに対するクエリを処理する分割統治法に不可欠な性質である。

functional graph の SCC

用途: 木DPができるようになるなど

functional graph $G$ を強連結成分分解して得られるグラフ $\tilde{G}$ は木である。

次数に基づくグラフの向き付けと出次数の定理

用途: 三角形カウントなど、一般グラフにおける $O(M\sqrt{M})$ アルゴリズムの計算量保証

任意の単純無向グラフ $G = (V, E)$(辺数を $M$ とする)において、各辺 $\{u, v\} \in E$ に対して以下のルールで向き付け(有向辺 $u \to v$ の作成)を行う。

  • $\deg(u) < \deg(v)$ のとき、$u \to v$ とする。
  • $\deg(u) = \deg(v)$ のとき、頂点番号が $u < v$ ならば $u \to v$ とする。

このとき、生成された有向グラフの任意の頂点の出次数(外へ向かう辺の数)は $\sqrt{2M}$ 以下となる。

証明を開く

ある頂点 $u$ に注目し、生成された有向グラフでの出次数を $k$ とする(つまり、$u$ から $k$ 個の頂点に向かって有向辺が出ている)。

  1. 向き付けのルール(次数が小さい方から大きい方へ向かう)より、$u$ が向いている先の $k$ 個の頂点はすべて、元の無向グラフにおいて次数が $\deg(u)$ 以上である。
  2. $u$ 自身が出次数 $k$ を持つため、当然ながら元の無向グラフでの次数 $\deg(u)$ は $k$ 以上である($\deg(u) \ge k$)。
  3. したがって、$u$ の行き先である $k$ 個の頂点は、すべて元の無向グラフにおいて次数が $k$ 以上である。
  4. ここで、グラフ全体の次数の総和は $2M$ である(握手補題)。
  5. グラフ内には「次数が $k$ 以上の頂点」が少なくとも $k$ 個($u$ の行き先の頂点群)存在することが確定した。これら $k$ 個の頂点だけで次数の和を計算しても $k \times k = k^2$ となる。

全体の次数の総和 $2M$ は、これら一部の頂点の次数の和 $k^2$ よりも必ず大きいため、 $$k^2 \le 2M$$ $$k \le \sqrt{2M}$$ が成り立つ。これにより、どのようなグラフであっても各頂点の出次数が高々 $O(\sqrt{M})$ に抑えられることが保証される。

連結成分を橋でつなげる

用途: 連結成分を橋で繋いで連結するときの数え上げ

$n$ 個の連結グラフ $G_1,\cdots,G_N$ があり、それらの頂点数を $s_1,\cdots,s_n$ とする。 このとき、これらを $n-1$ 個の橋を用いて連結にする方法の総数は次で与えられる。 $$\prod_{i = 1}^n s_i \left(\sum_{j = 1}^n s_i\right)^{n-2} = N^{n-2} \prod_{i = 1}^n s_i$$

理由(行列木定理による導出)を開く

各連結成分を1つの頂点に縮約した $n$ 頂点のグラフを考えます。成分 $i$ と成分 $j$ をつなぐ橋の選び方は $s_i s_j$ 通りあるため、これを辺の重みとみなして行列木定理を適用します。
全体の頂点数を $N = \sum_{i=1}^n s_i$ とすると、重み付きグラフのラプラシアン行列 $L$ は以下のようになります。

  • 非対角成分 ($i \neq j$): $L_{ij} = -s_i s_j$
  • 対角成分: $L_{ii} = \sum_{j \neq i} s_i s_j = s_i(N - s_i) = s_i N - s_i^2$

行列木定理より、求める木の総数は $L$ から $n$ 行目と $n$ 列目を取り除いた $(n-1) \times (n-1)$ の小行列 $L_0$ の行列式 $\det(L_0)$ に等しくなります。
対角行列 $D = \mathrm{diag}(s_1 N, \dots, s_{n-1} N)$ と、ベクトル $\mathbf{s} = (s_1, \dots, s_{n-1})^T$ を用いると、$L_0 = D - \mathbf{s}\mathbf{s}^T$ と表せます。
行列式補題($\det(A - uv^T) = \det(A)(1 - v^T A^{-1} u)$)を用いると、計算は次のように鮮やかに展開されます。 $$ \det(L_0) = \det(D) \left( 1 - \mathbf{s}^T D^{-1} \mathbf{s} \right) $$ $$ = \left( \prod_{i=1}^{n-1} s_i N \right) \left( 1 - \sum_{i=1}^{n-1} \frac{s_i^2}{s_i N} \right) $$ $$ = N^{n-1} \left( \prod_{i=1}^{n-1} s_i \right) \left( 1 - \frac{N - s_n}{N} \right) $$ $$ = N^{n-1} \left( \prod_{i=1}^{n-1} s_i \right) \left( \frac{s_n}{N} \right) = N^{n-2} \prod_{i=1}^n s_i $$

Prüferコード (Prüfer Code) の定義と性質

用途: 木の数え上げ(Cayleyの公式)、ラベル付き木と数列の全単射、次数制約付き木の生成

【定義】
$N$ 頂点のラベル付き木に対し、「葉(次数1の頂点)の中で最小のラベルを持つものを削除し、その隣接頂点のラベルを記録する」という操作を、木の頂点が残り2つになるまで繰り返して得られる、長さ $N-2$ の数列。

【重要な性質】

  • 完全な全単射(Bijection):
    $N$ 頂点のラベル付き木の集合と、$1$ から $N$ の値をとる長さ $N-2$ の数列の集合は完全に1対1対応する。これにより、ラベル付き木の総数が $N^{N-2}$ 通りであること(Cayleyの公式)が直ちに導かれる。
  • 次数と出現回数の関係:
    ある頂点 $v$ が Prüferコード内に出現する回数は、元の木におけるその頂点の次数 $d(v)$ から 1 を引いた値($d(v) - 1$)に等しい。コードに一度も出現しない頂点は、元の木の葉を意味する。
  • 線形時間 $O(N)$ での変換:
    優先度付きキュー(ヒープ)を用いると $O(N \log N)$ で変換・復元できるが、最小値の候補をポインタで適切に尺取り法的に管理することで、木から数列、数列から木への相互変換はともに $O(N)$ の計算量で実行可能である。
補足説明を開く(次数制約付き木の数え上げ)

各頂点の次数 $d_i$ が指定された木を数え上げる問題は、Prüferコードの性質により「長さ $N-2$ の数列に、各要素 $i$ を $d_i - 1$ 個ずつ配置する順列の総数」に帰着されます。この総数は多項係数 $\frac{(N-2)!}{\prod_{i=1}^N (d_i-1)!}$ を用いて $O(N)$ で計算可能です。

補グラフ上のBFS / 最短経路(未訪問頂点集合の管理)

用途: 元のグラフの辺数が多く補グラフが疎である(またはその逆で、補グラフ上の辺でBFSしたい)場合に高速に最短経路を求める

補グラフ $\bar{G}$ の辺数は $O(N^2)$ になるため愚直なBFSは間に合わない。 未訪問の頂点全体を std::set や std::list などのデータ構造で保持し、 ある頂点 $u$ から「元のグラフ $G$ で辺が存在しない(=補グラフで辺が存在する)未訪問頂点」のみに直接遷移して探索を行う。

補足説明を開く

頂点 $u$ の遷移先を探す際、未訪問頂点集合を走査しながら「$u$ の隣接リストに含まれる頂点」であればスキップし、「含まれない頂点」であればキューに追加して未訪問集合から削除する。 スキップが発生する回数の総和は元のグラフの辺数 $2M$ で抑えられるため、全体計算量は std::set を用いた場合 $O((N + M) \log N)$ となる。

Hallの結婚定理

用途: 2部マッチングの存在条件

2部グラフ $G = (U \cup V, E)$ において、$U$ のすべての頂点をカバーするマッチングが存在するための必要十分条件は、任意の $S \subseteq U$ に対して $|N(S)| \ge |S|$ が成り立つことである。ここで、$N(S)$ は $S$ に隣接する頂点の集合を表す。

Kőnigの定理

用途: 2部グラフにおける最大マッチングと最小頂点被覆の関係

2部グラフ $G = (U \cup V, E)$ において、最大マッチングの辺数は、最小頂点被覆の頂点数に等しい。 すなわち、 $$\text{最大マッチングの大きさ} = \text{最小頂点被覆の大きさ}$$ が成り立つ。ここで、頂点被覆とは、 グラフ中のすべての辺について、その両端点の少なくとも一方を含む頂点集合を表す。(頂点によるパスの被覆)

補足説明を開く

一般のグラフでは、最大マッチングの大きさと最小頂点被覆の大きさは必ずしも一致しないが、 2部グラフでは必ず一致する。そのため、最大マッチングを求めると、 同じ大きさの最小頂点被覆も構成できる。

特に、最大マッチング $M$ を求めたあと、 $U$ の未マッチ頂点からマッチング辺と非マッチング辺を交互にたどって到達可能な頂点集合を $Z_U, Z_V$ とすると、 $$ (U \setminus Z_U) \cup Z_V $$ が最小頂点被覆になる。 したがって、「最大マッチングを求める問題」と「最小頂点被覆を求める問題」が 2部グラフでは同じ値を持つという点が重要である。

また、Hallの結婚定理が「完全マッチングが存在する条件」を与えるのに対し、 Kőnigの定理は「最大マッチングの大きさ」と 「すべての辺を覆うために必要な最小頂点数」の関係を与える定理である。 競プロでは、2部マッチングを求めたあとに最小頂点被覆そのものを復元したい場合や、 マッチング問題を別の被覆問題へ変換する際に利用される。

最大独立集合

用途: グラフから互いに隣接しない頂点を最大数選ぶ問題

グラフ $G = (V, E)$ において、どの2頂点の間にも辺が存在しない頂点集合を独立集合(Independent Set)といい、 その中で頂点数が最大のものを最大独立集合という。 最大独立集合の大きさを $\alpha(G)$ と表す。

補足説明を開く

例えば、頂点集合 $S \subseteq V$ について、$S$ に含まれる異なる任意の2頂点の間に 辺が存在しなければ、$S$ は独立集合である。 「互いに直接つながっていない頂点を、できるだけ多く選ぶ」と考えるとよい。

最大独立集合と最小頂点被覆には補集合による重要な関係がある。 任意のグラフについて、 $$S\text{ が独立集合} \iff V\setminus S\text{ が頂点被覆}$$ が成り立つため、 $$\boxed{ \text{最大独立集合の大きさ} = |V|-\text{最小頂点被覆の大きさ} }$$ となる。

さらに、2部グラフではKőnigの定理より、 $$\text{最大マッチングの大きさ} = \text{最小頂点被覆の大きさ}$$ が成り立つ。したがって、 $$\boxed{ \text{最大独立集合の大きさ} = |V|-\text{最大マッチングの大きさ} }$$ となる。

つまり2部グラフでは、 最大マッチングを求めることで、最大独立集合の大きさも求められる。 さらに、最大マッチングから到達可能頂点集合を復元すれば、 最大独立集合そのものも構成できる。

最大マッチング $M$ に対して、左側の未マッチ頂点から交互道をたどり、 到達可能な頂点集合を $Z_U, Z_V$ とすると、 $$\boxed{ Z_U \cup (V\setminus Z_V) }$$ が最大独立集合になる。

競プロでは、問題文に「互いに隣接しない頂点を最大数選ぶ」といった条件が現れたとき、 それが2部グラフなら、最大独立集合 → 最小頂点被覆 → Kőnigの定理 → 最大マッチング という変換を考えるとよい。

最大流最小カット定理

用途: 最大フローの算出、および最小カット(燃やし埋め問題等)への帰着

ネットワーク $G = (V, E)$ におけるソース $s$ からシンク $t$ への最大流量(Max Flow)は、$s$ と $t$ を分離するカットの最小容量(Min Cut)に等しい。 $$\text{Max Flow}(s, t) = \text{Min Cut}(s, t)$$

補足説明を開く

「いくら流せるか」の最大値は、ネットワークを2つに分断する最も狭いボトルネック(カット)の容量で決定する。競プロでは、制約を満たすためのコスト最小化問題をグラフの「最小カット」に帰着して解く(いわゆる「燃やし埋め」など)際のアプローチとして多用される。

Dilworthの定理

用途: 半順序集合の最長反鎖・最小鎖分割の関係

半順序集合(DAG)において以下が成り立つ。 $$\text{最大反鎖長} = \text{最小鎖分割の分割数}$$

補足説明を開く

鎖とは任意の2要素が比較可能な部分集合、 反鎖とは異なる任意の2要素が比較不能な部分集合を表す。

半順序集合の大小関係を二部グラフに帰着させる事を考える。 具体的には、頂点を倍加し、x > y なる組に対して、L_x から R_y へと辺を貼る。 このようにして得られたグラフの最大独立集合が最大反鎖長である。

Dilworthの定理の双対

用途: 半順序集合の最長鎖・最小反鎖分割の関係

半順序集合(DAG)において以下が成り立つ。 $$\text{最大鎖長} = \text{最小反鎖分割の分割数}$$

Undirected Vertex Geography の必勝条件

用途: 無向グラフ上でのしりとりゲームの判定

無向グラフ $G$ と開始頂点 $s$ 上で行われる Undirected Vertex Geography において、先手必勝であるための必要十分条件は、$G$ のすべての最大マッチングが頂点 $s$ をカバーすること(すなわち、$s$ を含まない最大マッチングが存在しないこと)である。

計算量改善

unordered_mapの計算量

用途: 定数倍改善

vectorの参照に比べて10倍くらいの計算量がかかる。したがって、値域が判明しているときはvectorを用いるほうが良い。

Segtreeよりも平方分割のほうが優れるケース

用途: Mo's Algorithmなどと併用する

1点更新区間和取得クエリは、更新の回数が取得の回数よりずっと多いときには、セグ木よりも平方分割の方が早くなる。 (seg木 : 更新 O(lon N) / 取得 O(log N), 平方分割 : 更新 O(1) / 取得 O(√N))

平面走査

用途: Mo's Algorithmでは間に合わないときに使う

区間[l,r)に対するクエリが[0,l),[0,r)に対するクエリに分解できるときは、平面走査を行うことで対処できる。 (Mo's Algorithmを使う必要がない)

計算量は正しいはずなのに...!!

用途: TLEの原因が本当にわからないとき

実はlogが知らぬ間に発生しているかもしれない。例えば、mod逆元にはlogが必要である。

実装の工夫

累積和っぽいものを作るとき

用途: わからなくなったら見て

$S_{r} - S_{l}$ のように、区間の計算を2つに分けれるときには、積極的に分けるべし!

考察のTips

貪欲法の典型パターン

用途: ごちゃごちゃしない

「うまい評価関数を見つける」、「交換しても悪化しない」、「後に良いものを残す」、「辞書順最小」などがある。