この問題 a^b % 1000000007 を高速に計算するための 繰り返し二乗法(binary exponentiation) の仕組みを 図付きで詳しく解析・説明します。
a と b が与えられたとき、a^b % 1000000007 を 高速に正確に求める。
aは整数(最大10^9)→BigIntで表現bは整数(最大10^18)→BigIntが必須- 単純な
forループだと10^18回の繰り返しは間に合わない ⟶ よってO(log b)の繰り返し二乗法 を使う
a^b を次のように分解できる:
bが偶数のとき: a^b = (a^(b/2))^2
bが奇数のとき: a^b = a * a^(b-1)
この再帰的な性質を ループで効率的に計算していきます。
→ 3^13 % 1000000007 を計算したい
まず b を2進数に変換:
b = 13 = 1101₂
↑ ↑ ↑ ↑
8 4 0 1 ←(2^3, 2^2, 2^1, 2^0 の位置)
このことから:
3^13 = 3^(8 + 4 + 0 + 1)
= 3^8 * 3^4 * 3^1
つまり、2進数のビットが1のところだけ掛け算するイメージです。
| ループ | b(二進数) | bのLSB | base | result | 操作 |
|---|---|---|---|---|---|
| 0 | 1101₂ = 13 | 1 | 3 |
1 |
b奇数なので result ← result × base = 1×3 = 3 |
3 |
base ← base² = 3² = 9 | ||||
| 1 | 110₂ = 6 | 0 | 9 |
3 |
b偶数なので resultは更新せず |
| base ← 9² = 81 | |||||
| 2 | 11₂ = 3 | 1 | 81 |
3 |
result ← result × base = 3×81 = 243 |
243 |
base ← 81² = 6561 | ||||
| 3 | 1₂ = 1 | 1 | 6561 |
243 |
result ← result × base = 243×6561 = 1594323 |
1594323 |
base ← 6561² |
while (b > 0n) {
if (b % 2n === 1n) {
result = (result * a) % mod;
}
a = (a * a) % mod;
b >>= 1n;
}| 処理 | 説明 |
|---|---|
b % 2n === 1n |
最下位ビット(LSB)が1なら result に掛ける |
result = (result * a) % mod |
その時点の base を result に掛け、MODを取る |
a = (a * a) % mod |
次の2^iに備えて base を二乗(指数の倍に対応) |
b >>= 1n |
指数 b を1ビット右シフト → b = floor(b / 2) |
b = 13 = 1101₂
↓
[1] b LSB=1 → result *= a → a = a²
[2] b >>=1 → b=6 (LSB=0) → a = a²
[3] b >>=1 → b=3 (LSB=1) → *= a → a = a²
[4] b >>=1 → b=1 (LSB=1) → *= a → a = a²
終了(b=0)
| 項目 | 値 |
|---|---|
| 時間計算量 | O(log b) ≒ 60 回以下(最大) |
| 空間計算量 | O(1)(BigInt数個のみ) |
b = 123456789012345678は10^18オーバーの巨大整数- JavaScriptの
numberは 53bit 精度まで ⟶BigIntで安全な演算が可能
入力:
123456789 123456789012345678
出力(正解):
3599437
- 繰り返し二乗法は
bを 2進数で分解し、必要なべきだけを掛け合わせる O(log b)で非常に高速BigIntにより超巨大指数にも対応できる- メモリ使用も極小で、時間・メモリ制約の両方を余裕で満たす
| 提出日時 | 問題 | ユーザ | 言語 | 得点 | コード長 | 結果 | 実行時間 | メモリ | |
|---|---|---|---|---|---|---|---|---|---|
| 2025-07-21 14:41:38 | B29 - Power Hard | myoshizumi | Go (go 1.20.6) | 1000 | 1185 Byte | 1 ms | 1720 KiB | 詳細 | |
| 2025-07-21 14:37:11 | B29 - Power Hard | myoshizumi | PHP (php 8.2.8) | 1000 | 1196 Byte | 14 ms | 21356 KiB | 詳細 | |
| 2025-07-21 14:34:10 | B29 - Power Hard | myoshizumi | Python (CPython 3.11.4) | 1000 | 1211 Byte | 20 ms | 10640 KiB | 詳細 | |
| 2025-07-21 13:49:35 | B29 - Power Hard | myoshizumi | TypeScript 5.1 (Node.js 18.16.1) | 1000 | 890 Byte | 45 ms | 42916 KiB | 詳細 | |
| 2025-07-21 13:46:56 | B29 - Power Hard | myoshizumi | JavaScript (Node.js 18.16.1) | 1000 | 888 Byte | 42 ms | 42764 KiB | 詳細 |