Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions Algorithm/EuclideanAlgorithm/LeastCommonMultiple/atcoder/B27/B27.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// 以下に、**Go 1.20.6** を用いて **2つの正の整数 `A`, `B` の最小公倍数(LCM)を求める実装**を提示します。

// ---

// ## ✅ 処理概要

// * **入力**:標準入力(`fmt.Scan`)で `A B` を読み取る(1 ≤ A, B ≤ 10⁹)
// * **出力**:LCM(最小公倍数)
// * **型**:`int64` を使用(必要に応じて `math/big` 使用可)
// * **GCD**:ユークリッドの互除法
// * **LCM**:`a / GCD(a, b) * b`(順番に注意)

// ---

// ## ✅ Go実装(関数型、型付き、計算量考慮)

package main

import (
"fmt"
"os"
)

/**
* gcd は 2つの整数 a, b の最大公約数を返します。
* ユークリッドの互除法を使用。
*
* @param a int64 - 整数 a
* @param b int64 - 整数 b
* @return int64 - aとbの最大公約数
*/
func gcd(a int64, b int64) int64 {
for b != 0 {
a, b = b, a%b
}
return a
}

/**
* lcm は 2つの整数 a, b の最小公倍数を返します。
* lcm(a, b) = a / gcd(a, b) * b の順に計算してオーバーフローを防ぎます。
*
* @param a int64 - 整数 a
* @param b int64 - 整数 b
* @return int64 - aとbの最小公倍数
*/
func lcm(a int64, b int64) int64 {
return (a / gcd(a, b)) * b
}

/**
* main は標準入力から a, b を読み取り、
* 最小公倍数を標準出力に出力します。
*
* 入力例: 25 30
* 出力例: 150
*/
func main() {
var a, b int64
_, err := fmt.Scan(&a, &b)
if err != nil {
fmt.Fprintln(os.Stderr, "入力エラー:", err)
return
}

result := lcm(a, b)
fmt.Println(result)
}

// ## ✅ 入出力例

// ```
// 入力: 25 30
// 出力: 150

// 入力: 998244353 998244853
// 出力: 996492287418565109
// ```

// ---

// ## ✅ 計算量とリソース消費

// | 項目 | 内容 |
// | ------ | ------------------------------------------ |
// | 時間計算量 | O(log(min(a, b))): `gcd` のユークリッド互除法 |
// | メモリ使用量 | O(1): 数個の `int64` 変数のみ |
// | 最大出力対応 | `int64` → 約 `9.2 * 10^18` まで安全(64bit) |
// | 注意 | `a = 10^9, b = 10^9` でも LCM = `10^18` → OK |

// ---

// ## ✅ オーバーフローについて

// `int64` 上限は約 `9.2e18`。本問題の LCM の最大値は:

// ```
// LCM(10^9, 10^9) = 10^9
// × (10^9 / GCD(10^9, 10^9)) = 10^9 × 1 = 10^9
// ```

// または、異なる素数の場合は `10^9 * 10^9 = 1e18` → `int64` で安全!

// ---

// ## ✅ 解説図(例:LCM(25, 30))

// ```text
// Step 1: GCD(25, 30)
// 30 % 25 = 5
// 25 % 5 = 0 → GCD = 5

// Step 2: LCM = (25 / 5) * 30 = 5 * 30 = 150
// ```
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 以下に、Node.js (`fs` モジュール使用) を用いて制限内で最小公倍数(LCM)を求める実装を提示します。

// ## ✅ 特徴

// * 入力: `fs.readFileSync("/dev/stdin", "utf8")`(AtCoderなどで利用可)
// * 最小公倍数計算: `LCM(a, b) = a / GCD(a, b) * b`(オーバーフロー対策済)
// * 使用アルゴリズム: **ユークリッドの互除法** によるGCD計算

// ---

// ### ✅ 実装コード(Node.js, JavaScript)

const fs = require("fs");

/**
* 最小公倍数を求める関数
* @param {bigint} a - 正整数 A
* @param {bigint} b - 正整数 B
* @returns {bigint} - aとbの最小公倍数(LCM)
*/
function lcm(a, b) {
return (a / gcd(a, b)) * b;
}

/**
* 最大公約数(GCD)をユークリッドの互除法で求める関数
* @param {bigint} a - 整数 a
* @param {bigint} b - 整数 b
* @returns {bigint} - aとbの最大公約数
*/
function gcd(a, b) {
while (b !== 0n) {
const temp = b;
b = a % b;
a = temp;
}
return a;
}

// 入力読み込み
const input = fs.readFileSync("/dev/stdin", "utf8").trim().split(" ");
const A = BigInt(input[0]);
const B = BigInt(input[1]);

// 最小公倍数を出力
console.log(lcm(A, B).toString());

// ### ✅ 実行性能

// * **時間計算量**: O(log(min(A, B)))(ユークリッドの互除法)
// * **空間計算量**: O(1)
// * **BigInt**を用いることで **2^53 を超える範囲の整数にも対応**(例: `998244353 * 998244853`)

// ---

// ### ✅ サンプル入出力確認

// **入力:**

// ```
// 25 30
// ```

// **出力:**

// ```
// 150
// ```

// **入力:**

// ```
// 998244353 998244853
// ```

// **出力:**

// ```
// 996492287418565109
// ```
116 changes: 116 additions & 0 deletions Algorithm/EuclideanAlgorithm/LeastCommonMultiple/atcoder/B27/B27.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<!-- 以下に、**PHP 8.2.8** 向けに、**2つの整数 A, B の最小公倍数(LCM)を求める関数ベースの実装**を示します。

---

## ✅ 仕様概要

* **入力**:標準入力(例: `fgets(STDIN)`)で与えられる2つの整数 A, B(1 ≤ A, B ≤ 10⁹)
* **出力**:最小公倍数(LCM)
* **計算式**:

$$
\text{LCM}(A, B) = \frac{A}{\gcd(A, B)} \times B
$$

※ オーバーフロー防止のために順序に注意(`A / GCD` を先に行う)

---

## ✅ PHP 実装(型明示・関数化)

<?php

/**
* 最大公約数(GCD)をユークリッドの互除法で求める
*
* @param int $a - 正の整数
* @param int $b - 正の整数
* @return int - aとbの最大公約数
*
* 時間計算量:O(log(min(a, b)))
*/
function gcd(int $a, int $b): int {
while ($b !== 0) {
$temp = $b;
$b = $a % $b;
$a = $temp;
}
return $a;
}

/**
* 最小公倍数(LCM)を求める関数
*
* @param int $a - 正の整数
* @param int $b - 正の整数
* @return int|string - aとbの最小公倍数(オーバーフロー時にはstring)
*
* 処理順に注意:a / GCD → b を掛ける(int型上限対策)
*/
function lcm(int $a, int $b): int|string {
$g = gcd($a, $b);
$div = intdiv($a, $g);
$product = $div * $b;

// オーバーフロー対策(PHP_INT_MAXを超えた場合はstringに)
if ($product > PHP_INT_MAX) {
return bcmul((string)$div, (string)$b); // 多倍長整数で計算
}

return $product;
}

/**
* メイン処理(標準入力を読み取り、LCMを出力)
*
* @return void
*/
function main(): void {
$line = trim(fgets(STDIN));
[$a, $b] = array_map('intval', explode(' ', $line));

$result = lcm($a, $b);
echo $result . PHP_EOL;
}

main();

// ## ✅ 実行例

// **入力:**

// ```
// 25 30
// ```

// **出力:**

// ```
// 150
// ```

// ---

// ## ✅ 性能解析

// | 項目 | 内容 |
// | --------- | --------------------------------------- |
// | 時間計算量 | O(log(min(A, B))) (GCD部分がボトルネック) |
// | 空間計算量 | O(1)(GCD・LCM として数個の整数のみ使用) |
// | メモリ使用 | 数十バイト(変数 + 一時計算) |
// | オーバーフロー対応 | `PHP_INT_MAX` 超えを検知し `bcmul()`(多倍長演算)使用 |

// ---

// ## ✅ 多倍長処理の注意点

// * `PHP_INT_MAX ≒ 9223372036854775807`(64bit環境)
// * 例:`998244353 * 998244853 = 996492287418565109` → **OK**
// * ただし、`10^9 * 10^9 = 10^18` は string 処理推奨

// ---

// ## 🔚 備考

// * 必要に応じて `gmp` 関数での置換も可能です(例:`gmp_gcd`, `gmp_lcm`)
// * `bcmath` は標準で使えるため環境依存しにくいです
Loading