diff --git a/Algorithm/BinarySearch/atCoder/B11/B11.go b/Algorithm/BinarySearch/atCoder/B11/B11.go new file mode 100644 index 00000000..84f11b23 --- /dev/null +++ b/Algorithm/BinarySearch/atCoder/B11/B11.go @@ -0,0 +1,120 @@ +// 以下は、**Go言語** を使って「配列 A の中で X より小さい要素がいくつあるか」を求めるプログラムです。 +// 高速処理のため、**ソート + 二分探索** を用いています。 + +// --- + +// ## ✅ アルゴリズムの概要 + +// * `sort.Ints(A)` で昇順にソート(前処理): `O(N log N)` +// * `sort.Search()` を使って各クエリに対する `X` 未満の個数を高速取得: `O(Q log N)` +// * 入力は `bufio.Scanner`、出力は `bufio.Writer` で高速処理 + +// --- + +// ## ✅ Go 実装(型明示 + コメント付き) + +// ```go +package main + +import ( + "bufio" + "fmt" + "os" + "sort" + "strconv" +) + +func main() { + // 高速入出力設定 + reader := bufio.NewScanner(os.Stdin) + reader.Split(bufio.ScanWords) + writer := bufio.NewWriter(os.Stdout) + defer writer.Flush() + + // 整数読み取り関数 + readInt := func() int { + reader.Scan() + val, _ := strconv.Atoi(reader.Text()) + return val + } + + // 入力 N + var N int = readInt() + A := make([]int, N) + for i := 0; i < N; i++ { + A[i] = readInt() + } + + // ソート(前処理): O(N log N) + sort.Ints(A) + + // 入力 Q + var Q int = readInt() + for i := 0; i < Q; i++ { + X := readInt() + // 二分探索(X未満の要素数) + count := sort.Search(len(A), func(i int) bool { + return A[i] >= X + }) + fmt.Fprintln(writer, count) + } +} +// ``` + +// --- + +// ## ✅ 処理時間とメモリ使用量 + +// ### 時間計算量 + +// | 処理内容 | 時間計算量 | +// | ---------- | -------------------- | +// | ソート処理 | O(N log N) | +// | クエリ Q 回の探索 | O(Q log N) | +// | 合計 | O(N log N + Q log N) | + +// → 最大 `N, Q = 100000` でも `2 × 10⁶` 操作以下 → **1 秒以内で処理可能** + +// --- + +// ### メモリ使用量(推定) + +// | 要素 | 概要 | メモリ使用量(概算) | +// | ------ | --------------- | ------------------ | +// | 配列 `A` | `[]int`, 最大10⁵個 | 約 0.8 MB(8バイト×10⁵) | +// | 出力 | `Writer` バッファなど | 数 KB〜数十 KB 程度 | +// | 合計 | 入力/出力含めて数 MB 程度 | ✅ 1024 MiB 制限に余裕あり | + +// --- + +// ## ✅ 入力例と出力 + +// ### 入力 + +// ``` +// 5 +// 1 3 3 3 1 +// 2 +// 4 +// 3 +// ``` + +// ### 出力 + +// ``` +// 5 +// 2 +// ``` + +// --- + +// ## ✅ 解法の特徴まとめ + +// | 項目 | 内容 | +// | ------ | -------------------------------- | +// | ソート | `sort.Ints()`(O(N log N)) | +// | 探索 | `sort.Search()` で二分探索(X未満) | +// | 入出力高速化 | `bufio.Scanner` + `bufio.Writer` | +// | 実行時間 | 最大で 1 秒未満 | +// | メモリ | 数 MB 以下 | + diff --git a/Algorithm/BinarySearch/atCoder/B11/B11.js b/Algorithm/BinarySearch/atCoder/B11/B11.js new file mode 100644 index 00000000..90bf338f --- /dev/null +++ b/Algorithm/BinarySearch/atCoder/B11/B11.js @@ -0,0 +1,89 @@ +// 以下は、**JavaScript (Node.js)** を用いた解法です。高速なクエリ応答のために、配列 `A` を **ソートして二分探索**を使い、各 `X` に対して「未満の要素数」を効率よく求めます。 + +// ## ✅ 方針 + +// 1. **配列 A を昇順にソート**しておく(O(N log N))。 +// 2. 各クエリ `X` に対して **二分探索**で `A[i] < X` を満たす `i` の数を調べる(O(Q log N))。 +// 3. `fs` モジュールで高速入出力を行う。 + +// ## ✅ コード +const fs = require("fs"); + +// 高速入力 +const input = fs.readFileSync("/dev/stdin", "utf8").trim().split(/\s+/); + +let idx = 0; +const N = parseInt(input[idx++]); +const A = []; + +for (let i = 0; i < N; i++) { + A.push(parseInt(input[idx++])); +} + +A.sort((a, b) => a - b); // 昇順ソート + +const Q = parseInt(input[idx++]); +const results = []; + +for (let q = 0; q < Q; q++) { + const X = parseInt(input[idx++]); + results.push(lowerBound(A, X)); // X 未満の個数 +} + +// 二分探索(lower_bound):X より小さい要素数 +function lowerBound(arr, target) { + let left = 0; + let right = arr.length; + while (left < right) { + const mid = (left + right) >> 1; + if (arr[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + return left; +} + +// 出力(高速) +console.log(results.join("\n")); + +// ## ✅ 処理時間・メモリの見積り + +// * 時間計算量: + +// * `A` のソート:`O(N log N)` +// * 各クエリに対して `O(log N)` → `Q log N` +// * 合計:`O(N log N + Q log N)` → 最大で約 `2×10^6` 回程度の操作 → 十分高速(1 秒以内) + +// * 空間計算量: + +// * `A` 配列と `results` の保存 → O(N + Q) 要素 → 約 800KB〜1MB 程度 +// * メモリ制限(1024MiB)以内に収まる + +// --- + +// ## ✅ 入力例 1 の実行結果 + +// 入力: + +// ``` +// 15 +// 83 31 11 17 32 19 23 37 43 47 53 61 67 5 55 +// 5 +// 10 +// 20 +// 30 +// 40 +// 50 +// ``` + +// 出力: + +// ``` +// 1 +// 4 +// 5 +// 8 +// 10 +// ``` diff --git a/Algorithm/BinarySearch/atCoder/B11/B11.php b/Algorithm/BinarySearch/atCoder/B11/B11.php new file mode 100644 index 00000000..a7f120a8 --- /dev/null +++ b/Algorithm/BinarySearch/atCoder/B11/B11.php @@ -0,0 +1,115 @@ + + None: + input_data: List[str] = sys.stdin.read().split() + index: int = 0 + + # 配列の長さ N + N: int = int(input_data[index]) + index += 1 + + # 配列 A + A: List[int] = [int(input_data[i]) for i in range(index, index + N)] + index += N + + # ソート(前処理) O(N log N) + A.sort() + + # クエリ数 Q + Q: int = int(input_data[index]) + index += 1 + + # 各クエリ Xi に対して A 中の「Xi 未満の個数」を求める O(Q log N) + results: List[int] = [] + for i in range(Q): + X: int = int(input_data[index + i]) + count: int = bisect.bisect_left(A, X) # A[i] < X の個数 + results.append(count) + + # 出力(高速) O(Q) + sys.stdout.write('\n'.join(map(str, results)) + '\n') + +if __name__ == "__main__": + main() +# ``` + +# --- + +# ## ✅ 処理時間・メモリの見積もり + +# ### 時間計算量 + +# | 処理内容 | 時間計算量 | +# | --------- | ----------------------------- | +# | 入力の読み込み | O(N + Q) | +# | 配列 A のソート | O(N log N) | +# | 各クエリの処理 | O(Q log N) | +# | 合計 | O(N log N + Q log N)(≒ 2×10⁶) | + +# ✔️ 最大 `N = Q = 10^5` のときでも **余裕で 1秒以内** + +# --- + +# ### メモリ使用量(目安) + +# | 要素 | サイズ(概算) | +# | ------- | ------------------------- | +# | 配列 `A` | 約 `100,000 × 4B` = 400 KB | +# | クエリ `Q` | 約 `100,000 × 4B` = 400 KB | +# | その他 | 数MB以下 | + +# ✔️ 全体で **数MB** 程度 → 1024 MiB 制限に **余裕で収まる** + +# --- + +# ## ✅ 入力例の確認 + +# ### 入力 + +# ``` +# 5 +# 1 3 3 3 1 +# 2 +# 4 +# 3 +# ``` + +# ### 出力 + +# ``` +# 5 +# 2 +# ``` + +# --- + +# ご希望あれば、`matplotlib` を使って探索の過程を図解することも可能です。必要であればお知らせください。 diff --git a/Algorithm/BinarySearch/atCoder/B11/B11.ts b/Algorithm/BinarySearch/atCoder/B11/B11.ts new file mode 100644 index 00000000..90cb2cd7 --- /dev/null +++ b/Algorithm/BinarySearch/atCoder/B11/B11.ts @@ -0,0 +1,103 @@ +// 以下は、**TypeScript** + `fs` モジュールを用いて高速に入力を処理し、各クエリ `X` に対して「配列 A の中で X より小さい要素の個数」を求めるプログラムです。 + +// --- + +// ### ✅ アルゴリズム概要(再掲) + +// * 配列 `A` を昇順に **ソート**(`O(N log N)`) +// * 各クエリ `X` に対して **二分探索**で `X` 未満の要素数を求める(`O(log N)` × Q) + +// --- + +// ### ✅ TypeScript 実装(Node.js + fs) + +// ```ts +import * as fs from 'fs'; + +// 入力読み込み(高速) +const input: string[] = fs.readFileSync('/dev/stdin', 'utf8').trim().split(/\s+/); +let idx = 0; + +// 入力取得 +const N: number = parseInt(input[idx++]); +const A: number[] = []; + +for (let i = 0; i < N; i++) { + A.push(parseInt(input[idx++])); +} + +A.sort((a, b) => a - b); // 昇順ソート + +const Q: number = parseInt(input[idx++]); +const results: number[] = []; + +// 各クエリに対して lowerBound を実行 +for (let i = 0; i < Q; i++) { + const X: number = parseInt(input[idx++]); + results.push(lowerBound(A, X)); +} + +// 二分探索:X より小さい要素の数を返す +function lowerBound(arr: number[], target: number): number { + let left = 0; + let right = arr.length; + while (left < right) { + const mid = (left + right) >>> 1; // unsigned right shift で高速化 + if (arr[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + return left; +} + +// 結果出力 +console.log(results.join('\n')); +// ``` + +// --- + +// ### ✅ 処理時間・メモリの分析 + +// * **時間計算量**: + +// * `sort`:`O(N log N)` +// * `Q` 個のクエリに対して `O(log N)` → 合計 `O(Q log N)` +// * 制約最大 `N=10^5`, `Q=10^5` でも合計約 `2×10^6` 回の操作 → **十分高速**(1秒以内) + +// * **メモリ使用量**: + +// * `A`, `results`, 入力配列を保持 → 最大で `300,000` 要素程度 +// * 各要素は整数(8バイト以下) → **数MBで収まる**(1024 MiB 制限内) + +// --- + +// ### ✅ 入力例での確認 + +// 入力: + +// ``` +// 15 +// 83 31 11 17 32 19 23 37 43 47 53 61 67 5 55 +// 5 +// 10 +// 20 +// 30 +// 40 +// 50 +// ``` + +// 出力: + +// ``` +// 1 +// 4 +// 5 +// 8 +// 10 +// ``` + +// --- + +// ご希望あれば、`readline` を使った逐次読み込み版や、ブラウザ実行向けへの変換、型の強化(ジェネリクス)なども可能です。お気軽にどうぞ。 diff --git a/Algorithm/BinarySearch/atCoder/B11/README.md b/Algorithm/BinarySearch/atCoder/B11/README.md new file mode 100644 index 00000000..4aed70ff --- /dev/null +++ b/Algorithm/BinarySearch/atCoder/B11/README.md @@ -0,0 +1,180 @@ + +--- + +### ✅ 目次 + +1. 入力処理(fsによる読み込み) +2. 配列 `A` のソート処理 +3. 二分探索 `lowerBound()` の仕組み(図で詳しく) +4. 出力処理(配列の結果を join して出力) + +--- + +## 1. 🔰 入力処理(fs) + +```ts +const input: string[] = fs.readFileSync('/dev/stdin', 'utf8').trim().split(/\s+/); +``` + +### 🎯 処理内容 + +* `fs.readFileSync('/dev/stdin', 'utf8')` により **全体を一気に読み込み**。 +* `trim().split(/\s+/)` によって、**スペースや改行区切り**の数字列を **string\[]** として取得。 + +--- + +### 🧠 具体例 + +#### 入力 + +``` +5 +1 3 3 3 1 +2 +4 +3 +``` + +#### `input` 配列の状態: + +``` +input = [ + "5", // N + "1", "3", "3", "3", "1", // A + "2", // Q + "4", "3" // クエリX +] +``` + +--- + +## 2. 📊 配列 `A` のソート処理 + +```ts +A.sort((a, b) => a - b); +``` + +* JavaScriptの標準ソート(文字列ソート)ではなく、**数値ソート**。 +* 昇順に並び替える。 + +--- + +### 🧠 例:A = \[1, 3, 3, 3, 1] + +``` +Before sort: [1, 3, 3, 3, 1] +↓ +After sort: [1, 1, 3, 3, 3] +``` + +--- + +## 3. 🔍 二分探索(lowerBound) + +```ts +function lowerBound(arr: number[], target: number): number { + let left = 0; + let right = arr.length; + while (left < right) { + const mid = (left + right) >>> 1; + if (arr[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + return left; +} +``` + +--- + +### 🎯 意味 + +「**配列 arr の中で target より小さい要素はいくつあるか?**」 +➡️ `arr` はソート済なので、**二分探索**で調べられる! + +--- + +### 🧠 例:`A = [1, 1, 3, 3, 3]`, `target = 3` + +#### 初期状態 + +``` +arr = [1, 1, 3, 3, 3] +target = 3 +``` + +| left | mid | right | arr\[mid] | 判定 | 次の範囲 | +| ---- | --- | ----- | --------- | ---------- | ------------ | +| 0 | 2 | 5 | 3 | 3 >= 3 → ✖ | \[0, 2) | +| 0 | 1 | 2 | 1 | 1 < 3 → ✔ | \[2, 2) (終了) | + +➡️ 結果:**left = 2** → `3` より小さい要素は **2個** + +--- + +### 📘 イメージ図(探索範囲) + +``` +配列: [1, 1, 3, 3, 3] +index: 0 1 2 3 4 +target: 3 + + ↑ + [left=2] = 答え! +``` + +--- + +## 4. 🖨️ 出力処理 + +```ts +console.log(results.join('\n')); +``` + +* `results` にクエリごとの答えを配列で格納。 +* 最後に `join('\n')` により **Q行の出力**としてまとめて出力。 + +--- + +### 🧠 例:結果 = \[5, 2] + +``` +results = [5, 2] +console.log(results.join('\n')) → +5 +2 +``` + +--- + +## ✅ 全体フロー図(まとめ) + +``` + 入力 (fs.readFileSync) + ↓ + 文字列配列 input[] + ↓ + 配列Aの抽出・整形 + ↓ + Aをソート + ↓ + 各クエリに対して + ┌───────────────┐ + │ lowerBound() │ ←─── target X + └───────────────┘ + ↓ + 結果を配列に保存 + ↓ + join('\n')でまとめて出力 +``` + +--- +| [提出日時](https://atcoder.jp/contests/tessoku-book/submissions/me?desc=true&orderBy=created) | 問題 | ユーザ | 言語 | [得点](https://atcoder.jp/contests/tessoku-book/submissions/me?desc=true&orderBy=score) | [コード長](https://atcoder.jp/contests/tessoku-book/submissions/me?orderBy=source_length) | 結果 | [実行時間](https://atcoder.jp/contests/tessoku-book/submissions/me?orderBy=time_consumption) | [メモリ](https://atcoder.jp/contests/tessoku-book/submissions/me?orderBy=memory_consumption) | | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| 2025-07-06 23:34:52 | [B11 - Binary Search 2](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_cj) | [myoshizumi](https://atcoder.jp/users/myoshizumi) | [Go (go 1.20.6)](https://atcoder.jp/contests/tessoku-book/submissions/me?f.Language=5002) | 1000 | 803 Byte | | 42 ms | 3004 KiB | [詳細](https://atcoder.jp/contests/tessoku-book/submissions/67394394) | +| 2025-07-06 23:24:50 | [B11 - Binary Search 2](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_cj) | [myoshizumi](https://atcoder.jp/users/myoshizumi) | [PHP (php 8.2.8)](https://atcoder.jp/contests/tessoku-book/submissions/me?f.Language=5016) | 1000 | 887 Byte | | 76 ms | 32112 KiB | [詳細](https://atcoder.jp/contests/tessoku-book/submissions/67394238) | +| 2025-07-06 23:21:04 | [B11 - Binary Search 2](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_cj) | [myoshizumi](https://atcoder.jp/users/myoshizumi) | [Python (CPython 3.11.4)](https://atcoder.jp/contests/tessoku-book/submissions/me?f.Language=5055) | 1000 | 899 Byte | | 112 ms | 36232 KiB | [詳細](https://atcoder.jp/contests/tessoku-book/submissions/67394169) | +| 2025-07-06 23:15:49 | [B11 - Binary Search 2](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_cj) | [myoshizumi](https://atcoder.jp/users/myoshizumi) | [TypeScript 5.1 (Node.js 18.16.1)](https://atcoder.jp/contests/tessoku-book/submissions/me?f.Language=5058) | 1000 | 1048 Byte | | 126 ms | 76908 KiB | [詳細](https://atcoder.jp/contests/tessoku-book/submissions/67394068) | +| 2025-07-06 23:11:11 | [B11 - Binary Search 2](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_cj) | [myoshizumi](https://atcoder.jp/users/myoshizumi) | [JavaScript (Node.js 18.16.1)](https://atcoder.jp/contests/tessoku-book/submissions/me?f.Language=5009) | 1000 | 877 Byte | | 384 ms | 76448 KiB | [詳細](https://atcoder.jp/contests/tessoku-book/submissions/67393981) | \ No newline at end of file diff --git a/Algorithm/RSA encryption/Decrypting RSA encryption/DecryptingRSAencryption.js b/Algorithm/RSA encryption/Decrypting RSA encryption/DecryptingRSAencryption.js new file mode 100644 index 00000000..f4121145 --- /dev/null +++ b/Algorithm/RSA encryption/Decrypting RSA encryption/DecryptingRSAencryption.js @@ -0,0 +1,98 @@ +// 以下は、指定されたRSA復号処理をJavaScript(Node.js)で `fs` モジュールを使って実装するコードです。 +// また、**実行時間とメモリ使用量にも配慮した実装**となっており、**高速な累乗と逆元の計算**により効率化しています。 + +// ### ✅ 解法のポイント + +// * `n = p * q` +// * `phi(n) = (p - 1) * (q - 1)` +// * `d ≡ e⁻¹ mod phi(n)`(拡張ユークリッドで逆元計算) +// * `M ≡ E^d mod n`(繰り返し二乗法で復号) + +// ### ✅ Node.js コード(`fs`使用) + +const fs = require('fs'); + +// 入力取得 +const input = fs.readFileSync(0, 'utf8').trim(); +const [p, q, e, E] = input.split(' ').map(BigInt); + +// n, φ(n) +const n = p * q; +const phi = (p - 1n) * (q - 1n); + +// 拡張ユークリッド互除法で e^-1 mod φ(n) を求める +function modInv(a, m) { + let m0 = m, x0 = 0n, x1 = 1n; + while (a > 1n) { + let q = a / m; + [a, m] = [m, a % m]; + [x0, x1] = [x1 - q * x0, x0]; + } + return x1 < 0n ? x1 + m0 : x1; +} + +// 繰り返し二乗法で (base ^ exp) % mod を高速計算 +function modPow(base, exp, mod) { + let result = 1n; + base = base % mod; + while (exp > 0n) { + if (exp % 2n === 1n) result = (result * base) % mod; + base = (base * base) % mod; + exp = exp / 2n; + } + return result; +} + +// 秘密鍵 d を計算 +const d = modInv(e, phi); + +// 復号: M = E^d mod n +const M = modPow(E, d, n); + +// ASCII に変換して出力 +console.log(String.fromCharCode(Number(M))); + +// ### ✅ 実行方法 + +// ```bash +// node rsa_decode.js < input.txt +// ``` + +// `input.txt` に以下のような入力を記述: + +// ``` +// 23917 23929 8731 109861231 +// ``` + +// 出力: + +// ``` +// K +// ``` + +// --- + +// ### ✅ 時間・メモリ計算(目安) + +// * **時間計算量** + +// * `modInv`: O(log φ(n)) ≈ O(log(pq)) ≈ O(log 10^10) = 約 33 回程度 +// * `modPow`: O(log d) ≈ O(log φ(n)) 同様 +// * **メモリ** + +// * 使用する変数は全て BigInt (最大でも 64bit 数個) +// * メモリ消費量 ≈ 数十 KB 未満 + +// --- + +// ### ✅ 入力例2 検証 + +// ``` +// 21283 21313 2843 315549360 +// ``` + +// 出力: + +// ``` +// p +// ``` diff --git a/Algorithm/RSA encryption/Decrypting RSA encryption/DecryptingRSAencryption.py b/Algorithm/RSA encryption/Decrypting RSA encryption/DecryptingRSAencryption.py new file mode 100644 index 00000000..15d1d35b --- /dev/null +++ b/Algorithm/RSA encryption/Decrypting RSA encryption/DecryptingRSAencryption.py @@ -0,0 +1,29 @@ +from typing import Tuple + +def extgcd(a: int, b: int) -> Tuple[int, int, int]: + if b != 0: + c, y, x = extgcd(b, a % b) + y -= (a // b) * x + return c, x, y + return a, 1, 0 + + +def modpow(a: int, b: int, m: int) -> int: + ans = 1 + while 0 < b: + if b & 1 == 1: + ans = (ans * a) % m + a = (a * a) % m + b >>= 1 + return ans + + +p, q, e, E = map(int, input().split()) +n = p * q +n_prime = (p - 1) * (q - 1) + +c, x, y = extgcd(e, n_prime) +d = (x + n_prime) % n_prime +M = modpow(E, d, n) + +print(chr(M)) \ No newline at end of file diff --git a/Algorithm/RSA encryption/Decrypting RSA encryption/README.md b/Algorithm/RSA encryption/Decrypting RSA encryption/README.md new file mode 100644 index 00000000..9a1cef5c --- /dev/null +++ b/Algorithm/RSA encryption/Decrypting RSA encryption/README.md @@ -0,0 +1,170 @@ + +--- + +## 🔐 問題概要 + +RSA暗号では、以下のようにして送信者が暗号化したデータ(数値)を、受信者が復号(解読)します: + +--- + +### 📘 入力: + +``` +p, q, e, E +``` + +例: + +``` +p = 23917 +q = 23929 +e = 8731 +E = 109861231 +``` + +--- + +## 🧩 処理ステップと図解 + +--- + +### ① n と φ(n) の計算 + +#### 数式: + +```txt +n = p × q +φ(n) = (p - 1) × (q - 1) +``` + +#### 例: + +```txt +n = 23917 × 23929 = 572068093 +φ(n) = (23917 - 1) × (23929 - 1) = 23916 × 23928 = 572020248 +``` + +#### 図解: + +``` ++-------------------+ +| RSA モジュロ空間 | ++-------------------+ + p = 23917 + q = 23929 + ┌────────────────────┐ + │ n = p × q │ → 572068093 + └────────────────────┘ + ┌────────────────────┐ + │ φ(n) = (p-1)(q-1) │ → 572020248 + └────────────────────┘ +``` + +--- + +### ② 拡張ユークリッドで `d = e⁻¹ mod φ(n)` を求める + +#### 数式: + +``` +d ≡ e⁻¹ mod φ(n) +``` + +e の逆元を求めるために、拡張ユークリッドの互除法(Extended Euclidean Algorithm)を使います。 + +#### 図解: + +``` ++---------------------------------------+ +| 拡張ユークリッド互除法 | ++---------------------------------------+ +| e = 8731, φ(n) = 572020248 | +| 目的:8731 × d ≡ 1 mod 572020248 | +| 結果:d = 428126443 | ++---------------------------------------+ +``` + +※ `d` を求めるには以下のように「a×x + b×y = gcd(a,b)」の形にし、x を `mod m` で正に直します。 + +--- + +### ③ 復号処理:`M ≡ E^d mod n` を求める + +**ここがRSAの心臓部です!** + +#### 数式: + +``` +M ≡ E^d mod n +``` + +これを高速に行うために「繰り返し二乗法(Binary Exponentiation)」を使います。 + +#### 図解: + +``` + E = 109861231 + | + v ++--------------------------+ +| 繰り返し二乗法で | +| M = E^d mod n を計算 | +| d = 428126443 | +| n = 572068093 | ++--------------------------+ + +結果: +M = 75 ← ASCIIコード +``` + +--- + +### ④ ASCII変換 + +```txt +M = 75 → 'K' +``` + +#### 図解: + +``` ++------------------+ +| ASCII 変換 | ++------------------+ +| M = 75 → 'K' | ++------------------+ +``` + +--- + +## 🧪 全体の流れまとめ(チャート) + +```mermaid +graph TD; + A[入力: p, q, e, E] --> B[n = p × q] + B --> C[φ(n) = (p-1)(q-1)] + C --> D[d = e⁻¹ mod φ(n)] + D --> E[M = E^d mod n] + E --> F[文字 = ASCII(M)] +``` + +--- + +## ✅ 結果 + +``` +出力:K +``` + +--- + +## 🔚 まとめ + +| ステップ | 内容 | 実行時間・効率 | +| ------- | --------------- | ----------- | +| n, φ(n) | 乗算のみ | O(1) | +| d計算 | 拡張ユークリッド | O(log φ(n)) | +| 復号 | 繰り返し二乗法 | O(log d) | +| ASCII変換 | Number → String | O(1) | + +---