Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ランダムを楽しもう / Algorithm with Randomness

ランダムを楽しもう / Algorithm with Randomness

本スライドでは、以下の2つの内容を紹介します。

1.乱択アルゴリズム(乱数を使って問題を解くアルゴリズム)
2.ランダムな入力に対するアルゴリズム

square1001

April 16, 2022
Tweet

Other Decks in Programming

Transcript

  1. 米田 寛峻 ー Hirotaka Yoneda 2002 年生まれ [2021. 6. 19

    撮影] 競技プログラミングなどでは 「square1001」 として活動 IOI 2018・2020 銀メダル 2021 年東京大学入学 自己紹介
  2. 米田 寛峻 このスライドは 「パ研合宿 2021」※ 3 日目の講義で使用したものです 注意事項 • 90

    分程度で読むことが想定されています • 本スライドは入門的な教材であるため、ランダム性を使ったアル ゴリズムのすべてを網羅しているわけではありません ※ 「パ研合宿 2021」 は、2022 年 3 月 27 日 ~ 30 日に開催された、中高生向けのプログラミング (主 に競技プログラミング) の合宿です。 4 / 165
  3. 0 ランダムを使う? 本講義では、2 つのトピックを解説します 第 1 章 第 2 章

    乱択アルゴリズム ランダムな入力に 対するアルゴリズム 7 / 165
  4. 何回で当てられますか? 数当てゲーム ? ? ? ? ? ? ? ?

    ? ? 1-1 ※ もし可能ならば、2 人でプレイしてみましょう。 答え (10 枚のカードに書かれた数) は次のスライドに書かれています。 13 / 165
  5. とはいえ、実際の人間は決してランダムではないが… What happens if you ask people to pick a

    number `at random’ between 1 and 100? 77 69 7 100 9 (N = 6750) (https://telescoper.wordpress.com/2018/04/11/what-happens-if-you-ask-people-to-pick-a-number-at-random-between-1-and-100/) 17 / 165
  6. 平均で何回聞く必要があるか? 数当てゲーム 1 回質問して当たる確率は 10% 100.0% YES NO 90.0% YES

    NO 10.0% 9.0% 81.0% YES NO 8.1% 72.9% 4 回目の質問をする確率 = 72.9% 1-1 21 / 165
  7. 平均で何回聞く必要があるか? 数当てゲーム 1 回質問して当たる確率は 10% 100.0% YES NO 90.0% YES

    NO 10.0% 9.0% 81.0% YES NO 8.1% 72.9% YES NO 7.3% 65.6% YES NO 5 回目の質問をする確率 = 65.61% 1-1 22 / 165
  8. 平均で何回聞く必要があるか? 数当てゲーム 質問回数の平均 = 100% + 90% + 81% +

    72.9% + 65.61% + … = 1 + 0.9 + 0.92 + 0.93 + 0.94 + ⋯ = 10 平均的には 10 回でアタリを引ける! (実際の質問回数は運によって変わる) 1-1 23 / 165
  9. 数当てゲーム アルゴリズム 1 1, 2, …, 100 の順に当てる 当たったらゲームクリア アルゴリズム

    2 100, 99, …, 1 の順に当てる 当たったらゲームクリア 意地悪な入力だと 91 回 かかる! 91 92 93 94 95 96 97 98 99 100 (今度は逆順にしてみたらどうだろうか?) 1-1 28 / 165
  10. 数当てゲーム アルゴリズム 1 1, 2, …, 100 の順に当てる 当たったらゲームクリア アルゴリズム

    2 100, 99, …, 1 の順に当てる 当たったらゲームクリア 意地悪な入力だと 91 回 かかる! 意地悪な入力だと 91 回 かかる! 91 92 93 94 95 96 97 98 99 100 1 2 3 4 5 6 7 8 9 10 1-1 29 / 165
  11. 数当てゲーム このように、紹介したアルゴリズムには大きな違いがある 乱数を使わないアルゴリズム 乱数を使うアルゴリズム • 平均的なケースで 10 回 • 意地悪なケースだと

    91 回 → 意地悪なケースを必ず作れ るので、そのときに非効率的 になる • 平均的なケースで 10 回 • 意地悪なケースでも平均 10 回 → どんなケースでも本当に運が 悪いと 91 回かかるが、そんなこ とはほぼあり得ない 1-1 30 / 165
  12. 乱数を使わないアルゴリズム • 平均的なケースで 10 回 • 意地悪なケースだと 91 回 →

    意地悪なケースを必ず作れ るので、そのときに非効率的 になる 数当てゲーム このように、紹介したアルゴリズムには大きな違いがある 乱数を使うアルゴリズム • 平均的なケースで 10 回 • 意地悪なケースでも平均 10 回 → どんなケースでも本当に運が 悪いと 91 回かかるが、そんなこ とはほぼあり得ない 「サイコロを使う」 アルゴリズムが 利用できることもある! 1-1 31 / 165
  13. 「数当てゲーム」 の応用 応用例 1 円周率 𝜋 の計算 (「アルゴリズム×数学」 p. 96~97

    参照) 一辺が 1 の正方形に ランダムに 点を 𝑁 個打つ 何個が 「半径 1 の円」 に入るか数える? 1-1 32 / 165
  14. 「数当てゲーム」 の応用 応用例 1 円周率 𝜋 の計算 (「アルゴリズム×数学」 p. 96~97

    参照) 一辺が 1 の正方形に ランダムに 点を 𝑁 個打つ 何個が 「半径 1 の円」 に入るか数える? 𝑵 100 1 万 100 万 円内に入った数 80 7785 784772 (割合) × 4 3.2 3.114 3.139088 「円周率は大体 3.14」 1-1 33 / 165
  15. 数当てゲーム 応用例 1 円周率 𝜋 の計算 (「アルゴリズム×数学」 p. 96~97 参照)

    一辺が 1 の正方形に ランダムに 点を 𝑁 個打つ 何個が 「半径 1 の円」 に入るか数える? 𝑵 100 1 万 100 万 円内に入った数 80 7785 784772 (割合) × 4 3.2 3.114 3.139088 「円周率は大体 3.14」 このような手法を 「モンテカルロ法」 という 1-1 34 / 165
  16. 「数当てゲーム」 の応用 応用例 2 連結な確率の計算 10×10 のマス目がある 左上と右下以外の 98 マスに対して

    • 50% の確率で通れる • 50% の確率で通れない 左上 → 右下に行ける確率は? S G 1-1 36 / 165
  17. 「数当てゲーム」 の応用 応用例 2 連結な確率の計算 モンテカルロ法 を使って計算しよう! ランダムにマス目を作って 100 万回シミュレーション

    22,049 / 100 万回 連結 確率 約 2.2 % (2.176% ~ 2.234%) S G 1-1 条件が複雑なので モンテカルロ法以外では求めにくい! 38 / 165
  18. ここで扱う問題 問題 1-2 この中で 𝐾 番目に小さい数は? 24 58 49 77

    81 36 53 𝐾 = 4 番目に小さい数は 「53」 𝑁 個の整数 𝑎1 , 𝑎2 , … , 𝑎𝑁 が与えられる 40 / 165
  19. ここで扱う問題 問題 𝑁 個の整数 𝑎1 , 𝑎2 , … ,

    𝑎𝑁 が与えられる 1-2 この中で 𝐾 番目に小さい数は? 解法 配列 𝐴 = 𝐴1 , 𝐴2 , … , 𝐴𝑁 をソートする すると 𝐴𝐾 が答えになる 1 2 計算量 𝑂 𝑁 log 𝑁 41 / 165
  20. ここで扱う問題 問題 𝑁 個の整数 𝑎1 , 𝑎2 , … ,

    𝑎𝑁 が与えられる 1-2 この中で 𝐾 番目に小さい数は? 解法 配列 𝐴 = 𝐴1 , 𝐴2 , … , 𝐴𝑁 をソートする すると 𝐴 𝐾 が答えになる 1 2 計算量 𝑂 𝑁 log 𝑁 平均計算量 𝑶 𝑵 で この問題が解けてしまう! ※ 乱数を使わずに最悪計算量 𝑂 𝑁 で解くアルゴリズムもありますが、とても複雑です。 43 / 165
  21. Quick Select 1-2 アイデア 値を 1 つランダムに選んで 「それ以下のグループ」 「それ以上のグループ」 に分ける

    53 58 24 77 81 49 90 37 19 𝐾 = 5 番目に小さい値を求めたい Step 1. ランダムに 1 つの値を選ぶ (紫色) 46 / 165
  22. Quick Select 1-2 アイデア 値を 1 つランダムに選んで 「それ以下のグループ」 「それ以上のグループ」 に分ける

    53 58 24 77 81 49 90 37 19 𝐾 = 5 番目に小さい値を求めたい Step 2. 「37 以下」 「37 以上」 のグループに分ける 47 / 165
  23. Quick Select 1-2 アイデア 値を 1 つランダムに選んで 「それ以下のグループ」 「それ以上のグループ」 に分ける

    24 19 37 53 58 77 81 49 90 𝐾 = 5 番目に小さい値を求めたい Step 3. これをグループごとに並べる 48 / 165
  24. Quick Select 1-2 アイデア 値を 1 つランダムに選んで 「それ以下のグループ」 「それ以上のグループ」 に分ける

    24 19 37 53 58 77 81 49 90 「6 個の中から 2 番目に小さい値」 を求める問題になった! ※ 補足: 「37 未満のグループ」 と 「37」 は “5 番目の値より小さい” ことが分かるので、より小さな問題に言い換えられる 49 / 165
  25. Quick Select 1-2 24 19 37 53 58 77 81

    49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する この処理を終わるまで繰り返す 53 58 24 77 81 49 90 37 19 50 / 165
  26. Quick Select 1-2 この処理を終わるまで繰り返す 24 19 37 53 58 77

    81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 53 58 24 77 81 49 90 37 19 51 / 165
  27. Quick Select 1-2 この処理を終わるまで繰り返す 53 58 24 77 81 49

    90 37 19 24 19 37 53 58 77 81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 52 / 165
  28. Quick Select 1-2 この処理を終わるまで繰り返す 53 58 24 77 81 49

    90 37 19 24 19 37 53 58 77 81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 24 19 37 53 49 58 77 81 90 53 / 165
  29. Quick Select 1-2 この処理を終わるまで繰り返す 53 58 24 77 81 49

    90 37 19 24 19 37 53 58 77 81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 24 19 37 53 49 58 77 81 90 [𝐾 = 2] 54 / 165
  30. Quick Select 1-2 この処理を終わるまで繰り返す 53 58 24 77 81 49

    90 37 19 24 19 37 53 58 77 81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 24 19 37 53 49 58 77 81 90 [𝐾 = 2] 55 / 165
  31. Quick Select 1-2 この処理を終わるまで繰り返す 53 58 24 77 81 49

    90 37 19 24 19 37 53 58 77 81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 24 19 37 53 49 58 77 81 90 [𝐾 = 2] 24 19 37 49 53 58 77 81 90 56 / 165
  32. Quick Select 1-2 この処理を終わるまで繰り返す 53 58 24 77 81 49

    90 37 19 24 19 37 53 58 77 81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. 「以下」 「以上」 の 2 グループに分ける Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 24 19 37 53 49 58 77 81 90 [𝐾 = 2] 24 19 37 49 53 58 77 81 90 [𝐾 = 1] 57 / 165
  33. Quick Select 1-2 この処理を終わるまで繰り返す 53 58 24 77 81 49

    90 37 19 24 19 37 53 58 77 81 49 90 [𝐾 = 5] [𝐾 = 2] Step #1. 値を 1 つ ランダムに選ぶ Step #2. Step #3. グループごとに 分けて並べる Step #4. より小さな問題に する 24 19 37 53 49 58 77 81 90 [𝐾 = 2] 24 19 37 49 53 58 77 81 90 [𝐾 = 1] 「以下」 「以上」 の 2 グループに分ける よって 5 番目に小さい値は 「53」 この問題が解けた 58 / 165
  34. Quick Select の実装 1-2 再帰関数 を使って実装できます int kth_element(vector<int> A, int

    K) { int N = A.size(); int pos = rand() % N; vector<int> LA, RA; for (int i = 0; i < N; i++) { if (A[i] < A[pos]) { LA.push_back(i); } if (A[i] > A[pos]) { RA.push_back(i); } } if (LA.size() < K) { return kth_element(LA, K); } else if (N - RA.size() <= K) { return kth_element(RA, K - (N - RA.size())); } return A[pos]; } 59 / 165
  35. Quick Select の実装 1-2 再帰関数 を使って実装できます 1 値を 1 つランダムに選ぶ

    int kth_element(vector<int> A, int K) { int N = A.size(); int pos = rand() % N; vector<int> LA, RA; for (int i = 0; i < N; i++) { if (A[i] < A[pos]) { LA.push_back(i); } if (A[i] > A[pos]) { RA.push_back(i); } } if (LA.size() < K) { return kth_element(LA, K); } else if (N - RA.size() <= K) { return kth_element(RA, K - (N - RA.size())); } return A[pos]; } 60 / 165
  36. Quick Select の実装 1-2 再帰関数 を使って実装できます 1 値を 1 つランダムに選ぶ

    2 「選んだ値より小さい」 「選んだ値 より大きい」 のグループに分割 int kth_element(vector<int> A, int K) { int N = A.size(); int pos = rand() % N; vector<int> LA, RA; for (int i = 0; i < N; i++) { if (A[i] < A[pos]) { LA.push_back(i); } if (A[i] > A[pos]) { RA.push_back(i); } } if (LA.size() < K) { return kth_element(LA, K); } else if (N - RA.size() <= K) { return kth_element(RA, K - (N - RA.size())); } return A[pos]; } 61 / 165
  37. Quick Select の実装 1-2 再帰関数 を使って実装できます 1 値を 1 つランダムに選ぶ

    2 3 より小さな問題にする (ここで再帰関数を使う) int kth_element(vector<int> A, int K) { int N = A.size(); int pos = rand() % N; vector<int> LA, RA; for (int i = 0; i < N; i++) { if (A[i] < A[pos]) { LA.push_back(i); } if (A[i] > A[pos]) { RA.push_back(i); } } if (LA.size() < K) { return kth_element(LA, K); } else if (N - RA.size() <= K) { return kth_element(RA, K - (N - RA.size())); } return A[pos]; } 「選んだ値より小さい」 「選んだ値 より大きい」 のグループに分割 62 / 165
  38. Quick Select の実装 1-2 再帰関数 を使って実装できます 1 値を 1 つランダムに選ぶ

    4 「選んだ値」 が答えになったら終了 int kth_element(vector<int> A, int K) { int N = A.size(); int pos = rand() % N; vector<int> LA, RA; for (int i = 0; i < N; i++) { if (A[i] < A[pos]) { LA.push_back(i); } if (A[i] > A[pos]) { RA.push_back(i); } } if (LA.size() < K) { return kth_element(LA, K); } else if (N - RA.size() <= K) { return kth_element(RA, K - (N - RA.size())); } return A[pos]; } 2 3 より小さな問題にする (ここで再帰関数を使う) 「選んだ値より小さい」 「選んだ値 より大きい」 のグループに分割 63 / 165
  39. Quick Select の実装 1-2 これで完成! 1 値を 1 つランダムに選ぶ 4

    「選んだ値」 が答えになったら終了 int kth_element(vector<int> A, int K) { int N = A.size(); int pos = rand() % N; vector<int> LA, RA; for (int i = 0; i < N; i++) { if (A[i] < A[pos]) { LA.push_back(i); } if (A[i] > A[pos]) { RA.push_back(i); } } if (LA.size() < K) { return kth_element(LA, K); } else if (N - RA.size() <= K) { return kth_element(RA, K - (N - RA.size())); } return A[pos]; } 2 3 より小さな問題にする (ここで再帰関数を使う) 「選んだ値より小さい」 「選んだ値 より大きい」 のグループに分割 64 / 165
  40. Quick Select の実装 1-2 これで完成! 1 値を 1 つランダムに選ぶ 4

    「選んだ値」 が答えになったら終了 int kth_element(vector<int> A, int K) { int N = A.size(); int pos = rand() % N; vector<int> LA, RA; for (int i = 0; i < N; i++) { if (A[i] < A[pos]) { LA.push_back(i); } if (A[i] > A[pos]) { RA.push_back(i); } } if (LA.size() < K) { return kth_element(LA, K); } else if (N - RA.size() <= K) { return kth_element(RA, K - (N - RA.size())); } return A[pos]; } 2 3 より小さな問題にする (ここで再帰関数を使う) 「選んだ値より小さい」 「選んだ値 より大きい」 のグループに分割 Quick Select の計算量は どうなるのか? 重要な課題 65 / 165
  41. Quick Select の計算量 1-2 … 運が最悪の場合 毎回 「最小の値」 or 「最大の値」

    を選び サイズが 1 ずつしか減らないパターン 𝑁 + 𝑁 − 1 + ⋯ + 1 = 1 2 𝑁 𝑁 + 1 = 𝑂 𝑁2 しかし、こんなことが起こる確率は 実質的にゼロに等しい 計算量 → 「平均的な運」 の場合はどうなるか? 66 / 165
  42. Quick Select の計算量 1-2 1 ステップで、「平均的なケースで」 サイズは何倍になるか? 𝐾 = 2

    の場合 𝐾 = 6 の場合 平均 10 → 5.4 (0.54 倍) 平均 10 → 6.6 (0.66 倍) 具体例 (𝑁 = 10 の場合) で考えてみよう 67 / 165
  43. Quick Select の計算量 1-2 1 ステップでどのように分かれるのかを考えよう < 𝐾 = 6

    の場合 > 6 7 8 9 1 9 8 7 6 5 平均 0.66 倍 どんな場合でも 「平均 0.75 倍」 以下になる! ※ 𝐾 = 𝑁/2 のとき、𝑁 が大きくなれば 「0.75 倍」 に近づき、これが最悪ケースになる 68 / 165
  44. Quick Select の計算量 1-2 「平均的な運」 の場合 … 1 回目の長さの平均 =

    N 2 回目の長さの平均 = 0.75 N 以下 3 回目の長さの平均 = 0.56 N 以下 4 回目の長さの平均 = 0.42 N 以下 5 回目の長さの平均 = 0.32 N 以下 (長さの合計) ≦ N + 0.75N + 0.56N + … = 𝑁 ⋅ 1 + 0.75 + 0.752 + 0.753 + ⋯ = 4𝑁 = 𝑂 𝑁 × 0.75 × 0.75 × 0.75 × 0.75 69 / 165
  45. Quick Select の計算量 1-2 「平均的な運」 の場合 … 1 回目の長さの平均 =

    N 2 回目の長さの平均 = 0.75 N 以下 3 回目の長さの平均 = 0.56 N 以下 4 回目の長さの平均 = 0.42 N 以下 5 回目の長さの平均 = 0.32 N 以下 (長さの合計) ≦ N + 0.75N + 0.56N + … = 𝑁 ⋅ 1 + 0.75 + 0.752 + 0.753 + ⋯ = 4N × 0.75 × 0.75 × 0.75 × 0.75 よって全体計算量は 𝑶 𝑵 70 / 165
  46. 問題例 1-3 JOI 2018 本選 3 「団子職人」 H×W のマス目に 赤・緑・白の団子がある

    上→下、左→右の順に 「赤・緑・白」 なら取れる 最大いくつ取れるか? 制約 (小課題 1) H, W ≦ 4 (小課題 2) H, W ≦ 10 (小課題 3) H, W ≦ 3000 今回は 「小課題 2」 (33 点解法) を扱います 72 / 165
  47. 問題例 1-3 JOI 2018 本選 3 「団子職人」 実は 「乱択アルゴリズム」 で解ける

    「ランダムに取れる団子を選ぶ」 を 取れなくなるまで繰り返す 1 の処理を 10,000 回繰り返す その中でスコア最大のものを答える 1 2 → H, W ≦ 10 くらいなら最適解が出せる! ※ 補足: 筆者は本番で最初満点解法が思いつかなかったので、まずこの解法を実装して 33 点を取りました 1 2 3 4 5 73 / 165
  48. 1 章のまとめ 1-3 乱数を使うと得することもある! 1 乱数を使って得することも 例: 計算量の改善 2 モンテカルロ法で

    複雑な確率を見積もれる 3 「配列の K 番目に小さい値」 は計算量 O(N) 43 66 79 28 61 12 71 94 64 35 74 / 165
  49. 「ランダムな入力」 とは? 2-1 競技プログラミングの問題などでは 問題文 𝑁 個の整数 𝐴1 , 𝐴2

    , … , 𝐴𝑁 が与えられる. 𝐴1 + 𝐴2 + ⋯ + 𝐴𝑁 を求めるプログラムを作れ. 入力 入力は以下の形式で標準入力から与えられる. 𝑁 𝐴1 𝐴2 ⋯ 𝐴𝑁 出力 標準出力に,求める桁数を 1 行で出力せよ. 制約 • 1 ≤ 𝑁 ≤ 100 000 • 0 ≤ 𝐴𝑖 ≤ 109 制約を満たすどんなケースでも 「正解」 する プログラムを作る必要がある ※ 1.2 節 「数当てゲーム」 の考え方と同じ いつも最悪ケースを考える必要がある 77 / 165
  50. 「ランダムな入力」 とは? 2-1 一方で、現実の問題を解くときは 問題文 𝑁 個の整数 𝐴1 , 𝐴2

    , … , 𝐴𝑁 が与えられる. 𝐴1 + 𝐴2 + ⋯ + 𝐴𝑁 を求めるプログラムを作れ. 入力 入力は以下の形式で標準入力から与えられる. 𝑁 𝐴1 𝐴2 ⋯ 𝐴𝑁 出力 標準出力に,求める桁数を 1 行で出力せよ. 制約 • 1 ≤ 𝑁 ≤ 100 000 • 0 ≤ 𝐴𝑖 ≤ 109 • 𝐴𝑖 はランダムに生成される  New! ランダムな入力とは? ランダムな入力とは、制約の範囲内で乱数を用いて 作られた入力のこと 特に断らなければ、それぞれの値 (右の例だと 𝐴𝑖 ) が一様な乱数で生成されるものとする 「入力はランダム」 でも十分なときがある 78 / 165
  51. ソートとは? 2-2 ソート: 𝑁 個の数 𝐴1 , 𝐴2 , …

    , 𝐴𝑁 を小さい順に並べる問題 43 66 79 28 61 12 71 94 64 35 12 28 35 43 61 64 66 71 79 94 マージソートや Quick Sort で計算量 𝑂 𝑁 log 𝑁 なのは有名 82 / 165
  52. ソート: 𝑁 個の数 𝐴1 , 𝐴2 , … , 𝐴𝑁

    を小さい順に並べる問題 ソートとは? 2-2 43 66 79 28 61 12 71 94 64 35 12 28 35 43 61 64 66 71 79 94 マージソートや Quick Sort で計算量 𝑂 𝑁 log 𝑁 なのは有名 ソートが平均 O(N) でできる! 84 / 165
  53. ランダムな入力 2-2 目的 𝑁 個の実数 𝑎1 , 𝑎2 , …

    , 𝑎𝑁 を小さい順に並べたい 制約 • 0 ≤ 𝑎𝑖 < 1 • 𝒂𝒊 は制約の範囲で一様ランダムに生成される やりたいのは、こういうこと 85 / 165
  54. ソートのアルゴリズム 2-2 アルゴリズム 1 値を 1/𝑁 ごとに区切って、配列の値をグループ分けする 2 各グループに対して (計算量

    𝑂 𝑛2 で) ソートする 3 ソートされた結果を全体でつなげる 0.0~0.1 0.1~0.2 0.2~0.3 0.3~0.4 0.4~0.5 0.5~0.6 0.6~0.7 0.7~0.8 0.8~0.9 0.9~1.0 0.28 0.61 0.94 90 / 165
  55. ソートのアルゴリズム 2-2 アルゴリズム 1 値を 1/𝑁 ごとに区切って、配列の値をグループ分けする 2 各グループに対して (計算量

    𝑂 𝑛2 で) ソートする 3 ソートされた結果を全体でつなげる 0.0~0.1 0.1~0.2 0.2~0.3 0.3~0.4 0.4~0.5 0.5~0.6 0.6~0.7 0.7~0.8 0.8~0.9 0.9~1.0 0.43 0.66 0.79 0.28 0.61 0.12 0.71 0.94 0.64 0.35 91 / 165
  56. ソートのアルゴリズム 2-2 アルゴリズム 1 値を 1/𝑁 ごとに区切って、配列の値をグループ分けする 2 各グループに対して (計算量

    𝑂 𝑛2 で) ソートする 3 ソートされた結果を全体でつなげる 0.0~0.1 0.1~0.2 0.2~0.3 0.3~0.4 0.4~0.5 0.5~0.6 0.6~0.7 0.7~0.8 0.8~0.9 0.9~1.0 0.43 0.66 0.79 0.28 0.61 0.12 0.71 0.94 0.64 0.35 ソート完了! 92 / 165
  57. ソートのアルゴリズム 2-2 0.0~0.1 0.1~0.2 0.2~0.3 0.3~0.4 0.4~0.5 0.5~0.6 0.6~0.7 0.7~0.8

    0.8~0.9 0.9~1.0 一般のデータの場合 一般のデータの場合、1 つのグループに密集する 「意地悪な」 ケースが作れる すると、アルゴリズムの計算量が 𝑂 𝑁2 になる x 0 x 0 x 0 x 0 x 0 x 0 x 10 x 0 x 0 x 0 コスト = 100 ※ コストは各箱に対する 「入っている個数の 2 乗」 の合計とする (計算量の目安になる) 94 / 165
  58. ソートのアルゴリズム 2-2 ランダムなデータの場合 でも、ランダムなら、前のような例は普通起こらない (相当運が悪くない限り) 理由は、ランダム = 「偏りがない」 から 0.0~0.1

    0.1~0.2 0.2~0.3 0.3~0.4 0.4~0.5 0.5~0.6 0.6~0.7 0.7~0.8 0.8~0.9 0.9~1.0 x 0 x 0 x 1 x 2 x 1 x 0 x 2 x 1 x 1 x 2 コスト = 16 Example 1 95 / 165
  59. ソートのアルゴリズム 2-2 0.0~0.1 0.1~0.2 0.2~0.3 0.3~0.4 0.4~0.5 0.5~0.6 0.6~0.7 0.7~0.8

    0.8~0.9 0.9~1.0 ランダムなデータの場合 でも、ランダムなら、前のような例は普通起こらない (相当運が悪くない限り) 理由は、ランダム = 「偏りがない」 から x 1 x 3 x 0 x 0 x 2 x 1 x 0 x 1 x 2 x 0 コスト = 20 Example 2 96 / 165
  60. 最頻値 196 ソートの計算量 2-2 N = 100 の場合 コストの確率分布は次の通りです (100

    万回シミュレーション) あれ、𝑶 𝑵𝟐 ではなさそう? 100 / 165
  61. ソートの計算量 2-2 実は 「1 つの箱に入る個数の 2 乗」 の期待値は 2 –

    1/N 𝐴𝑖 がその箱に入っている場合 𝑥𝑖 = 1 (確率 1/𝑁)、そうでない場合 𝑥𝑖 = 0 とする 証明 𝑥1 + 𝑥2 + ⋯ + 𝑥𝑁 2 = 𝑥1 2 + 𝑥2 2 + ⋯ + 𝑥𝑁 2 + 2 𝑥1 𝑥2 + 𝑥1 𝑥3 + ⋯ + 𝑥𝑁−1 𝑥𝑁 の期待値を求めたい 期待値は全部 1/𝑁 (𝑥𝑖 = 1 のときだけ 𝑥𝑖 2 = 1 なので) 期待値は全部 1/𝑁2 (𝑥𝑖 = 1 かつ 𝑥𝑗 = 1 のときだけ 𝑥𝑖 𝑥𝑗 = 1 なので) = 𝑁 ⋅ 1 𝑁 + 2 ⋅ 1 2 𝑁 𝑁 − 1 ⋅ 1 𝑁2 = 2 − 1 𝑁 期待値 101 / 165
  62. ナップザック問題 2-3 次のような問題を考えよう 「500 円以内で最大何 kcal まで食べられる?」 220 円 350

    kcal 290 円 380 kcal 180 円 250 kcal 110 円 200 kcal ※ 1 つの食品につき最大 1 回しか選べない 104 / 165
  63. ナップザック問題 2-3 次のような問題を考えよう 「500 円以内で最大何 kcal まで食べられる?」 220 円 350

    kcal 290 円 380 kcal 180 円 250 kcal 110 円 200 kcal ※ 1 つの食品につき最大 1 回しか選べない 答え 630 kcal 105 / 165
  64. ナップザック問題 2-3 このように、以下の問題を 「0-1 ナップザック問題」 という 𝑁 種類の商品が 1 つずつある

    商品 𝑖 の価値は 𝑣𝑖 で、重さは 𝑤𝑖 (𝑣𝑖 , 𝑤𝑖 は正の実数) 全体の重さが 𝑊 以下になる選び方の中で、 価値の合計は最大いくつになるか? その中でいくつかの商品を選んで持ち帰ることを考える 106 / 165
  65. ナップザック問題 2-3 ナップザック問題を高速に解くのは、難しいとされる (NP 困難) 解法 1 全探索すると、計算量 𝑂 2𝑁

    かかる 解法 2 半分全列挙をしても、計算量 𝑂 2𝑁/2 かかる 𝑁 ≤ 30 程度までしか通用しない 𝑁 ≤ 60 程度までしか通用しない 解法 3? 動的計画法 (DP) を使った解法は 「𝑣𝑖 , 𝑤𝑖 が実数」 なので通用しない! 107 / 165
  66. ナップザック問題 2-3 このように、以下の問題を 「0-1 ナップザック問題」 という 𝑁 個の商品が 1 つずつある

    商品 𝑖 の価値は 𝑣𝑖 で、重さは 𝑤𝑖 (𝑣𝑖 , 𝑤𝑖 は正の実数) 全体の重さが 𝑊 以下になる選び方の中で、 価値の合計は最大いくつになるか? 解法 1 全パターン調べ上げる: 𝑂 2𝑁 解法 2 半分全列挙: 𝑂 2𝑁/2 解法 3? 動的計画法は、𝑣𝑖 , 𝑤𝑖 が整数とは限らないので通用しない でも、入力がランダムだとどうなる?
  67. ランダムな入力 2-3 目的 𝑁 個の商品に対して、ナップザック問題を解きたい 制約 • 0 ≤ 𝑣𝑖

    < 1, 0 ≤ 𝑤𝑖 ≤ 1 • 𝒗𝒊 , 𝒘𝒊 は制約の範囲で一様ランダムに生成される やりたいのは、こういうこと 109 / 165
  68. 「緩和問題」 を考えよう 2-3 問題 ところで、ナップザック問題は、次のように定式化できます 𝑥1 , 𝑥2 , …

    , 𝑥𝑛 を 𝑥𝑖 ∈ 0, 1 となるように定める ここで、𝑤1 𝑥1 + 𝑤2 𝑥2 + ⋯ + 𝑤𝑁 𝑥𝑁 ≤ 𝑊 を満たす必要がある このとき、𝑣1 𝑥1 + 𝑣2 𝑥2 + ⋯ + 𝑣𝑁 𝑥𝑁 の最大値は? ※ 「𝑥𝑖 が 0 または 1」 という意味 110 / 165
  69. 「緩和問題」 を考えよう 2-3 問題 突然ですが、この条件を “緩和” した問題を考えてみましょう 𝑥1 , 𝑥2

    , … , 𝑥𝑛 を 𝟎 ≤ 𝒙𝒊 ≤ 𝟏 となるように定める ここで、𝑤1 𝑥1 + 𝑤2 𝑥2 + ⋯ + 𝑤𝑁 𝑥𝑁 ≤ 𝑊 を満たす必要がある このとき、𝑣1 𝑥1 + 𝑣2 𝑥2 + ⋯ + 𝑣𝑁 𝑥𝑁 の最大値は? つまり 「ある商品を 0.5 個取る」 などを許すということ 111 / 165
  70. 「緩和問題」 を考えよう 2-3 問題 突然ですが、この条件を “緩和” した問題を考えてみましょう 𝑥1 , 𝑥2

    , … , 𝑥𝑛 を 𝟎 ≤ 𝒙𝒊 ≤ 𝟏 となるように定める ここで、𝑤1 𝑥1 + 𝑤2 𝑥2 + ⋯ + 𝑤𝑁 𝑥𝑁 ≤ 𝑊 を満たす必要がある このとき、𝑣1 𝑥1 + 𝑣2 𝑥2 + ⋯ + 𝑣𝑁 𝑥𝑁 の最大値は? 緩和問題は、貪欲法で解ける 112 / 165
  71. 「緩和問題」 の解法 2-3 220 円 350 kcal 290 円 380

    kcal 180 円 250 kcal 110 円 200 kcal アイデア (カロリー) ÷ (値段) の高い順に取るのが絶対に得! 現在 0 kcal 残り 500 円 113 / 165
  72. 「緩和問題」 の解法 2-3 220 円 350 kcal 290 円 380

    kcal 180 円 250 kcal 110 円 200 kcal アイデア (カロリー) ÷ (値段) の高い順に取るのが絶対に得! 現在 200 kcal 残り 390 円 +200 kcal 114 / 165
  73. 「緩和問題」 の解法 2-3 220 円 350 kcal 290 円 380

    kcal 180 円 250 kcal 110 円 200 kcal アイデア (カロリー) ÷ (値段) の高い順に取るのが絶対に得! 現在 550 kcal 残り 170 円 +350 kcal 115 / 165
  74. 「緩和問題」 の解法 2-3 220 円 350 kcal 290 円 380

    kcal 180 円 250 kcal 110 円 200 kcal アイデア (カロリー) ÷ (値段) の高い順に取るのが絶対に得! 現在 786 kcal 残り 0 円 +236 kcal 116 / 165
  75. 「緩和問題」 の解法 2-3 220 円 350 kcal 290 円 380

    kcal 180 円 250 kcal 110 円 200 kcal アイデア (カロリー) ÷ (値段) の高い順に取るのが絶対に得! 現在 786 kcal 残り 0 円 +236 kcal これが最適! 117 / 165
  76. 「緩和問題」 の性質 2-3 重要な性質 ≦ ナップザック 問題の解 786 kcal 理由:

    ナップザック問題の方が、条件が真にきついから 119 / 165
  77. 「緩和問題」 の性質 2-3 重要な性質 ≦ 786 kcal 理由: ナップザック問題の方が、条件が真にきついから 確実に

    786 kcal 以下 このように、緩和問題には 「上界」 が分かるという性質がある 121 / 165
  78. 分枝限定法 2-3 分枝限定法とは? • 前から順 (ここでは 𝑣𝑖 /𝑤𝑖 の大き い順)

    に決めていく DFS のよう に探索する • (現在得られている最良の解) ≧ (緩和問題の解) になったら、 探索を枝刈りする • この枝刈りによって、高速化を図る 80 = BEST 78? 87? 87? 分枝限定法のイメージ • DFS の各ステップで緩和解を計算 123 / 165
  79. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 0 kcal 残り 170 円 124 / 165
  80. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 0 kcal 残り 170 円 • 緩和解 = 「これ以上あり得ない」 は 257 kcal 257? 125 / 165
  81. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 100 kcal 残り 110 円 257? 257? • 緩和解 = 「これ以上あり得ない」 は 257 kcal 126 / 165
  82. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 180 kcal 残り 60 円 257? 257? 257? • 緩和解 = 「これ以上あり得ない」 は 257 kcal 127 / 165
  83. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 180 kcal 残り 60 円 • 緩和解 = 「これ以上あり得ない」 は 233 kcal 257? 257? 257? 233? 128 / 165
  84. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 220 kcal 残り 20 円 • 緩和解 = 「これ以上あり得ない」 は 233 kcal 257? 257? 257? 233? 233? 129 / 165
  85. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 220 kcal 残り 20 円 • これで 「ベストな解」 は 220 kcal に 257? 257? 257? 233? 233? 220 (BEST) 130 / 165
  86. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 180 kcal 残り 60 円 • 緩和解 = 「これ以上あり得ない」 は 233 kcal 257? 257? 257? 233? 233? 220 (BEST) 131 / 165
  87. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 180 kcal 残り 60 円 • 緩和解 = 「これ以上あり得ない」 は 200 kcal 257? 257? 257? 233? 233? 220 (BEST) 200? 132 / 165
  88. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 180 kcal 残り 60 円 • 緩和解 = 「これ以上あり得ない」 は 200 kcal 257? 257? 257? 233? 233? 220 (BEST) 200? BEST を超える望みはないので 枝刈りできる! 133 / 165
  89. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 100 kcal 残り 110 円 • 緩和解 = 「これ以上あり得ない」 は 257 kcal 257? 257? 257? 233? 233? 220 (BEST) 200? 134 / 165
  90. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 100 kcal 残り 110 円 • 緩和解 = 「これ以上あり得ない」 は 230 kcal 257? 257? 257? 233? 233? 220 (BEST) 200? 230? 135 / 165
  91. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 190 kcal 残り 40 円 • 緩和解 = 「これ以上あり得ない」 は 230 kcal 257? 257? 257? 233? 233? 220 (BEST) 200? 230? 230? 136 / 165
  92. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 230 kcal 残り 0 円 • 緩和解 = 「これ以上あり得ない」 は 230 kcal 257? 257? 257? 233? 233? 220 (BEST) 200? 230? 230? 230? 137 / 165
  93. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 230 kcal 残り 0 円 257? 257? 257? 233? 233? 220 200? 230? 230? 230? • これで 「ベストな解」 は 230 kcal に 230 (BEST) 138 / 165
  94. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 230 kcal 残り 0 円 257? 257? 257? 233? 233? 220 200? 230? 230? 230? • これで 「ベストな解」 は 230 kcal に 230 (BEST) (中略…) 139 / 165
  95. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 0 kcal 残り 170 円 • 緩和解 = 「これ以上あり得ない」 は 257 kcal 257? 257? 257? 233? 233? 220 200? 230? 230? 230? 230 (BEST) 160? 210? 140 / 165
  96. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 0 kcal 残り 170 円 • 緩和解 = 「これ以上あり得ない」 は 216 kcal 257? 257? 257? 233? 233? 220 200? 230? 230? 230? 230 (BEST) 160? 210? 216? 141 / 165
  97. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 0 kcal 残り 170 円 • 緩和解 = 「これ以上あり得ない」 は 216 kcal 257? 257? 257? 233? 233? 220 200? 230? 230? 230? 230 (BEST) 160? 210? 216? これは、BEST な解より小さい! 142 / 165
  98. 分枝限定法 2-3 これをナップザック問題に適用してみよう! A B C D E kcal 100

    80 90 40 20 price 60 50 70 40 30 𝑣𝑖 ÷ 𝑤𝑖 1.667 1.600 1.286 1.000 0.667 現在 0 kcal 残り 170 円 • 緩和解 = 「これ以上あり得ない」 は 216 kcal 257? 257? 257? 233? 233? 220 200? 230? 230? 230? 230 (BEST) 160? 210? 216? これで、最適解 = 230 が分かった 143 / 165
  99. 分枝限定法 2-3 257? 257? 257? 233? 233? 220 200? 230?

    230? 230? 230 (BEST) 160? 210? 216? 分枝限定法の利用 • 今回は、𝑣𝑖 /𝑤𝑖 の大きい順に探索 • 右図のように 「バッサリ」 枝刈ること ができるのが、分枝限定法の利点 144 / 165
  100. 分枝限定法 2-3 257? 257? 257? 233? 233? 220 200? 230?

    230? 230? 230 (BEST) 160? 210? 216? 分枝限定法の利用 • 今回は、𝑣𝑖 /𝑤𝑖 の大きい順に探索 • 右図のように 「バッサリ」 枝刈ること ができるのが、分枝限定法の利点 探索する状態数は 𝟐𝑵 通りからどのくらい減る? 重要な課題 145 / 165
  101. 分枝限定法 2-3 どうして状態数が少なくなるのか? 直感的な説明 「緩和解の大きい解から順に探索する」 とい う仮定をする (実際それに近い動きをする) 1 (緩和解)

    - (実際の解) ≦ 1/N の解は O(N) 回探索すればきっと見つかるはず 2 ランダムなので、「ほぼピッタリ」 な解がいずれ見つかるはず! その後すぐ (緩和解) < (2 で得られた解) になって探索が終了する 3 151 / 165
  102. 問題例 2-4 問題 𝑁 個の点 𝑋1 , 𝑌1 , 𝑋2

    , 𝑌2 , … , 𝑋𝑁 , 𝑌𝑁 がある 𝑋𝑖 − 𝑋𝑗 𝑌𝑖 − 𝑌 𝑗 の最大値は? 制約 𝑁 ≤ 106, 𝑋𝑖 ≤ 109, 𝑌𝑖 ≤ 109 入力はランダム この長方形の面積を 最大化したい 153 / 165
  103. 問題例 2-4 実は、「右上頂点」 としてあり得るものは 右図の例では 5 通りしかない! この長方形の面積を 最大化したい 理由

    仮にそれ以外の点 (青色) が 右上頂点になるとする すると、これより面積が絶対に 大きくなる右上頂点が存在する 条件 どんな 𝑗 に対しても 𝑋𝑖 ≥ 𝑋𝑗 , 𝑌𝑖 ≥ 𝑌 𝑗 となる点 𝑋𝑖 , 𝑌 𝑗 154 / 165
  104. 問題例 2-4 同様に、左上頂点としてあり得るものは 右図の例では 2 通りしかない! この長方形の面積を 最大化したい 条件 どんな

    𝑗 に対しても 𝑋𝑖 ≤ 𝑋𝑗 , 𝑌𝑖 ≤ 𝑌 𝑗 となる点 𝑋𝑖 , 𝑌 𝑗 5×2 = 10 通りの全探索だけで 最適解が求められる! 155 / 165
  105. 問題例 2-4 同様に、左上頂点としてあり得るものは 右図の 2 通りしかない! この長方形の面積を 最大化したい 条件 どんな

    𝑗 に対しても 𝑋𝑖 ≤ 𝑋𝑗 , 𝑌𝑖 ≤ 𝑌 𝑗 となる点 𝑋𝑖 , 𝑌 𝑗 5×2 = 10 通りの全探索だけで 最適解が求められる! 探索するケースは 𝑵𝟐 通りからどのくらい減る? 重要な課題 156 / 165
  106. 問題例 2-4 相対的な位置関係だけを考えよう 1, 2, … , 𝑁 のランダムな順列 𝑝1

    , 𝑝2 , … , 𝑝𝑁 を考える 𝑖 番目の点が 𝑖, 𝑝𝑖 にあるとする • すると、右上頂点になり得る条件は 「𝑝𝑖 が 𝑝1 , 𝑝2 , … , 𝑝𝑖 の中で最大値」 → 確率は 1/𝑖 157 / 165
  107. 問題例 2-4 相対的な位置関係だけを考えよう 1, 2, … , 𝑁 のランダムな順列 𝑝1

    , 𝑝2 , … , 𝑝𝑁 を考える 𝑖 番目の点が 𝑖, 𝑝𝑖 にあるとする • すると、右上頂点になり得る条件は 「𝑝𝑖 が 𝑝1 , 𝑝2 , … , 𝑝𝑖 の中で最大値」 → 確率は 1/𝑖 よって、右上頂点の個数の期待値は 𝟏 + 𝟏 𝟐 + 𝟏 𝟑 + ⋯ + 𝟏 𝑵 ≈ 𝐥𝐨𝐠𝒆 𝑵 158 / 165
  108. 問題例 2-4 結論 探索すべき 「右上頂点」 の個数は平均 log𝑒 𝑁 個 探索すべき

    「左下頂点」 の個数も平均 log𝑒 𝑁 個 よって、探索すべき長方形は log𝑒 𝑁 2 個! アルゴリズム 1 2 点を 𝑋𝑖 の昇順 ・ 𝑌𝑖 の昇順にソートして、順列 𝑝 を求める 「右上頂点」 「左下頂点」 を列挙する 計算量 𝑂 𝑁 計算量 𝑂 𝑁 log 𝑁 3 長方形を全探索 𝑂 log2 𝑁 159 / 165
  109. 問題例 2-4 結論 探索すべき 「右上頂点」 の個数は平均 log𝑒 𝑁 個 探索すべき

    「左下頂点」 の個数も平均 log𝑒 𝑁 個 よって、探索すべき長方形は log𝑒 𝑁 2 個! アルゴリズム 1 2 点を 𝑋𝑖 の昇順 ・ 𝑌𝑖 の昇順にソートして、順列 𝑝 を求める 「右上頂点」 「左下頂点」 を列挙する 計算量 𝑂 𝑁 計算量 𝑶 𝑵 𝐥𝐨𝐠 𝑵  本当に? 3 長方形を全探索 𝑂 log2 𝑁 160 / 165
  110. 問題例 2-4 結論 探索すべき 「右上頂点」 の個数は平均 log𝑒 𝑁 個 探索すべき

    「左下頂点」 の個数も平均 log𝑒 𝑁 個 よって、探索すべき長方形は log𝑒 𝑁 2 個! アルゴリズム 1 2 点を 𝑋𝑖 の昇順 ・ 𝑌𝑖 の昇順にソートして、順列 𝑝 を求める 「右上頂点」 「左下頂点」 を列挙する 計算量 𝑂 𝑁 計算量 𝑶 𝑵 𝐥𝐨𝐠 𝑵  本当に? 3 長方形を全探索 𝑂 log2 𝑁 ランダムな配列のソートは 𝑶 𝑵 でできる! 161 / 165
  111. 問題例 2-4 結論 探索すべき 「右上頂点」 の個数は平均 log𝑒 𝑁 個 探索すべき

    「左下頂点」 の個数も平均 log𝑒 𝑁 個 よって、探索すべき長方形は log𝑒 𝑁 2 個! アルゴリズム 1 2 点を 𝑋𝑖 の昇順 ・ 𝑌𝑖 の昇順にソートして、順列 𝑝 を求める 「右上頂点」 「左下頂点」 を列挙する 計算量 𝑂 𝑁 計算量 𝑶 𝑵 3 長方形を全探索 𝑂 log2 𝑁 162 / 165
  112. 問題例 2-4 結論 探索すべき 「右上頂点」 の個数は平均 log𝑒 𝑁 個 探索すべき

    「左下頂点」 の個数も平均 log𝑒 𝑁 個 よって、探索すべき長方形は log𝑒 𝑁 2 個! アルゴリズム 1 2 点を 𝑋𝑖 の昇順 ・ 𝑌𝑖 の昇順にソートして、順列 𝑝 を求める 「右上頂点」 「左下頂点」 を列挙する 計算量 𝑂 𝑁 計算量 𝑶 𝑵 3 長方形を全探索 𝑂 log2 𝑁 よって、この問題は 平均 𝑶 𝑵 で解けた! 163 / 165
  113. 2 章のまとめ 2-4 「一般のデータ」 と 「ランダムなデータ」 はどう違うか? (再掲) 一般のデータ ランダムなデータ

    データは基本的に偏っていない 偏ってないデータも、意地悪なデータもある 164 / 165
  114. 2 章のまとめ 2-4 一般のデータの世界 • ソートは計算量 𝑂 𝑁 log 𝑁

    • ナップザック問題は計算量 𝑂 2𝑁/2 などなど… 私たちが普段競プロで取り組んでいるの は 「一般のデータの世界」 「データがランダムなこと」 で得することもある ランダムなデータの世界 • ソートは計算量 𝑂 𝑁 • ナップザック問題も十分高速 などなど… 「偏りのない性質」 を利用して、速く・効 率的に・単純に解ける場合もある! 165 / 165