ユークリッドの互除法メニュー【ユークリッドの互除法・3 つ以上の整数の最大公約数・最小公倍数・ax + by = c・拡張ユークリッドの互除法】
【STEP: 1】コード
// 2 つの整数 A , B の最大公約数(gcd(A , B))を高速に求めるアルゴリズム
reader.on('close', () => {
const [A, B] = lines[0].split(' ').map(Number);
let a = Math.max(A, B); // A , B のうち大きい方
let b = Math.min(A, B); // A , B のうち小さい方
while (a && b) { // a と b の双方が true の間
a %= b; // 小さい方で大きい方を割り 大きい方をその余りで置き換え…
[a, b] = [b, a]; // a, b の値を置換 (a %= b なので 値を入れ替える前は a < b)
}
console.log(a);
});
2 つの整数 A , B の最大公約数(gcd(A , B))を高速に求めるアルゴリズム
をユークリッドの互除法
って云うらしい。
【STEP: 2】コード
// 3 つ以上の整数の最大公約数を求める演算 gcd(...gcd(gcd(gcd(a,b),c),d)...)
reader.on('close', () => {
const N = Number(lines[0]);
const A = []; // N 個の整数
for (let i = 1; i <= N; i++) {
A.push(Number(lines[i]));
}
while (A.length >= 2) { // A の要素数が 2 以上の間ユークリッドの互除法をループ
// ここから ユークリッドの互除法
let a = Math.max(A[0], A[1]); // A[0], A[1] のうち大きい方
let b = Math.min(A[0], A[1]); // A[0], A[1] のうち小さい方
while (a && b) { // a と b の双方が true の間
a %= b; // 小さい方で大きい方をわり 大きい方をその余りで置き換え…
[a, b] = [b, a]; // // a, b の値を置換
}
// ここまで
A.splice(0, 2, a); // 0 番目から 2 個の要素を削除し 0 番目に a を埋め込み
}
console.log(...A);
});
A[0], A[1] の最大公約数 a を求め AからA[0], A[1]を削除し 代わりに a を 埋め込み。Aの要素数が 1 になるまで処理を繰り返し…。
【STEP: 3】コード
// lcm(A,B) = A×B/gcd(A,B) = 最小公倍数
reader.on('close', () => {
const [A, B] = lines[0].split(' ').map(Number);
// ここから ユークリッドの互除法
let a = Math.max(A, B);
let b = Math.min(A, B);
while (a && b) {
a %= b;
[a, b] = [b, a];
}
// ここまで
console.log(A * B / a); // 最小公倍数 = 元の値を乗算し 最大公約数で 除算
});
A, B の最小公倍数…。
- ユークリッドの互除法 で 最大公約数 a を求める。
- A ✕ B ÷ a = 最小公倍数 となる。
【STEP: 4】コード
// Ax + By = C の整数解 x , y の値を出力
reader.on('close', () => {
const [A, B, C] = lines[0].split(' ').map(Number);
let [x, y] = [0, 0];
switch (A > B) {
case true:
[x, y] = [1, -parseInt(A / B)];
break;
case false:
[x, y] = [-parseInt(B / A), 1];
break;
}
console.log(x, y);
});
x または y が 1 であるような解の組の値を出力なので これでいいのかな??
【FINAL】コード
reader.on('close', () => {
let [a, b] = lines[0].split(' ').map(Number);
let [x, y] = [1, 0];
let [nx, ny] = [0, 1];
while (a % b) {
let tmpx = x - parseInt(a / b) * nx;
let tmpy = y - parseInt(a / b) * ny;
a %= b;
[a, b] = [b, a];
[x, y] = [nx, ny];
[nx, ny] = [tmpx, tmpy];
}
console.log(nx, ny);
});
色々なサイトの解説も参照しながら試行錯誤しているうちに こんな感じになりました。正直 イマイチ 理解できていない。まだまだですね。(^_^;
【FINAL】コード 2
reader.on('close', () => {
function extgcd(a, b) {
if (b) {
const [c, y, x] = extgcd(b, a % b);
let yy = y;
yy -= Math.floor(a / b) * x;
return [c, x, yy];
}
return [a, 1, 0];
}
const [A, B] = lines[0].split(' ').map(Number);
const [C, X, Y] = extgcd(A, B);
console.log(X, Y);
});
問題文の疑似コードを参照。
コメント