From 2e3ce3cc40f7c04e75418a97c87fffae30da2246 Mon Sep 17 00:00:00 2001 From: myoshizumi Date: Mon, 21 Jul 2025 14:44:32 +0900 Subject: [PATCH 1/2] =?UTF-8?q?atcoder=20B29=20-=20Power=20Hard=20?= =?UTF-8?q?=E7=B9=B0=E3=82=8A=E8=BF=94=E3=81=97=E4=BA=8C=E4=B9=97=E6=B3=95?= =?UTF-8?q?=EF=BC=88Binary=20Exponentiation=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Binary Exponentiation/atcoder/B29/B29.go | 116 +++++++++++++ .../Binary Exponentiation/atcoder/B29/B29.js | 66 ++++++++ .../Binary Exponentiation/atcoder/B29/B29.php | 115 +++++++++++++ .../Binary Exponentiation/atcoder/B29/B29.py | 106 ++++++++++++ .../Binary Exponentiation/atcoder/B29/B29.ts | 89 ++++++++++ .../atcoder/B29/README.md | 154 ++++++++++++++++++ 6 files changed, 646 insertions(+) create mode 100644 Mathematics/Binary Exponentiation/atcoder/B29/B29.go create mode 100644 Mathematics/Binary Exponentiation/atcoder/B29/B29.js create mode 100644 Mathematics/Binary Exponentiation/atcoder/B29/B29.php create mode 100644 Mathematics/Binary Exponentiation/atcoder/B29/B29.py create mode 100644 Mathematics/Binary Exponentiation/atcoder/B29/B29.ts create mode 100644 Mathematics/Binary Exponentiation/atcoder/B29/README.md diff --git a/Mathematics/Binary Exponentiation/atcoder/B29/B29.go b/Mathematics/Binary Exponentiation/atcoder/B29/B29.go new file mode 100644 index 00000000..76034466 --- /dev/null +++ b/Mathematics/Binary Exponentiation/atcoder/B29/B29.go @@ -0,0 +1,116 @@ +// 以下は **Go 1.20.6** に対応した `a^b % 1000000007` を高速に計算する実装です。 + +// --- + +// ## ✅ 要件と対応内容 + +// | 項目 | 内容 | +// | ------ | ----------------------------------------- | +// | 入力 | `a`:int型 (最大 10^9)、`b`:最大 10^18(文字列として取得) | +// | 計算方法 | **繰り返し二乗法(Binary Exponentiation)** | +// | 型の扱い | `a`: `int64`、`b`: `*big.Int`(任意精度整数) | +// | 計算時間 | `O(log b)`(最大でも ≒60回) | +// | メモリ使用量 | 数十KB程度(`big.Int` 使用) | + +// --- + +// ## ✅ Goコード(`main.go`) + +// ```go +package main + +import ( + "bufio" + "fmt" + "math/big" + "os" + "strings" +) + +const MOD int64 = 1000000007 + +/** + * modPow は (a^b) % mod を高速に計算する関数(bは任意精度) + * + * @param a int64 底(1 ≤ a ≤ 10^9) + * @param b *big.Int 指数(1 ≤ b ≤ 10^18 まで対応) + * @param mod int64 法(通常は 1000000007) + * @return int64 計算結果 a^b % mod + */ +func modPow(a int64, b *big.Int, mod int64) int64 { + result := int64(1) + base := a % mod + zero := big.NewInt(0) + two := big.NewInt(2) + bCopy := new(big.Int).Set(b) // b を破壊しないようにコピー + + for bCopy.Cmp(zero) > 0 { + if new(big.Int).Mod(bCopy, two).Cmp(zero) != 0 { + result = (result * base) % mod + } + base = (base * base) % mod + bCopy.Div(bCopy, two) + } + + return result +} + +/** + * main は標準入力を読み込み、a^b % MOD を出力する + */ +func main() { + reader := bufio.NewReader(os.Stdin) + line, _ := reader.ReadString('\n') + parts := strings.Fields(line) + + var a int64 + var b big.Int + fmt.Sscan(parts[0], &a) + b.SetString(parts[1], 10) + + result := modPow(a, &b, MOD) + fmt.Println(result) +} + +// ## ✅ 実行例 + +// #### 入力 + +// ``` +// 123456789 123456789012345678 +// ``` + +// #### 出力 + +// ``` +// 3599437 +// ``` + +// --- + +// ## ✅ 処理性能分析 + +// | 項目 | 値 | +// | ------ | ---------------------- | +// | 時間計算量 | `O(log b)`(最大でも約60回) | +// | 実行時間 | 数ミリ秒(Goは非常に高速) | +// | メモリ使用量 | 数十 KB 程度(`big.Int`の数個) | + +// --- + +// ## ✅ 備考:なぜ `*big.Int` を使うのか? + +// * Go の `int64` は最大で `2^63 - 1 ≒ 9.2e18` ⇒ `10^18` を超えると不正確 +// * `math/big` パッケージを使えば任意精度整数として安全に指数演算が可能 + +// --- + +// ## ✅ 補足:最速を目指すなら + +// * `math/big` の `.Exp()` 関数を使っても計算可能ですが、`modPow` の方が処理流れが明確です: + +// ```go +// res := new(big.Int).Exp(big.NewInt(a), b, big.NewInt(MOD)) +// fmt.Println(res.Int64()) +// ``` + diff --git a/Mathematics/Binary Exponentiation/atcoder/B29/B29.js b/Mathematics/Binary Exponentiation/atcoder/B29/B29.js new file mode 100644 index 00000000..47bc19ce --- /dev/null +++ b/Mathematics/Binary Exponentiation/atcoder/B29/B29.js @@ -0,0 +1,66 @@ +// 以下は、JavaScript(Node.js 18.16.1)で、与えられた整数 `a` と巨大な指数 `b` に対して、 +// `a^b mod 1000000007` を高速に計算するプログラムです。 + +// ### ✅ 特徴 + +// * **高速べき乗法(繰り返し二乗法)** を使用 +// * **BigInt対応**(`b` は最大 `10^18` まで扱える) +// * `fs` モジュールで標準入力から読み込み +// * 計算時間は最大でも **O(log b)**、メモリも極めて少なく済みます + +// --- + +// ### ✅ コード(`a^b mod 1000000007`) + +// ```javascript +// Node.js 18.16.1 環境を想定 +const fs = require('fs'); + +const MOD = 1000000007n; + +/** + * a^b % mod を繰り返し二乗法で計算する + * @param {bigint} base - 底(a) + * @param {bigint} exponent - 指数(b) + * @param {bigint} mod - 法(1000000007) + * @returns {bigint} - a^b % mod の結果 + */ +function modPow(base, exponent, mod) { + let result = 1n; + base = base % mod; + while (exponent > 0n) { + if (exponent % 2n === 1n) { + result = (result * base) % mod; + } + base = (base * base) % mod; + exponent = exponent / 2n; + } + return result; +} + +// 入力読み込み +const input = fs.readFileSync('/dev/stdin', 'utf8').trim().split(' '); +const a = BigInt(input[0]); +const b = BigInt(input[1]); + +// 計算して出力 +const result = modPow(a, b, MOD); +console.log(result.toString()); + +// ### ✅ 実行方法 + +// UNIX環境(Linux / macOS)などで、次のようにファイルから入力できます: + +// ```bash +// node main.js < input.txt +// ``` + +// --- + +// ### ✅ 補足 + +// | 特性 | 内容 | +// | ------ | --------------------------- | +// | 時間計算量 | `O(log b)` | +// | メモリ使用量 | 約数百 KB 以下 | +// | 安全性 | `BigInt` 使用で `10^18` まで対応可能 | diff --git a/Mathematics/Binary Exponentiation/atcoder/B29/B29.php b/Mathematics/Binary Exponentiation/atcoder/B29/B29.php new file mode 100644 index 00000000..cb31ec37 --- /dev/null +++ b/Mathematics/Binary Exponentiation/atcoder/B29/B29.php @@ -0,0 +1,115 @@ +