🎯
【Java】最大公約数・最小公倍数
最大公約数
整数a
と整数b
の最大公約数は、お互いの素因数について指数の最小値を取ることで求めることができます。
コード例
import java.util.*;
public class Main {
// 素因数分解
// 整数 a 及び b を受け取り、素因数分解をおこなって (素因数=個数) の連想配列を返す
static HashMap<Integer, Integer> factorize(int n) {
HashMap<Integer, Integer> primes = new HashMap<>();
for (int i = 2; i * i <= n; i++) {
if (n % i > 0) {
continue;
}
int exp = 0;
while (n % i == 0) {
exp++;
n /= i;
}
primes.put(i, exp);
}
if (n != 1) {
primes.put(n, 1);
}
return primes;
}
// 連想配列 primes を受け取り、最大公約数を返す
static int calcGcd(int a, int b) {
HashMap<Integer, Integer> tableA = factorize(a);
HashMap<Integer, Integer> tableB = factorize(b);
HashMap<Integer, Integer> tableGcd = new HashMap<>();
for (int prime : tableA.keySet()) {
int exp = tableA.get(prime);
if (tableB.containsKey(prime)) {
exp = Math.min(exp, tableB.get(prime));
tableGcd.put(prime, exp);
}
}
int gcd = 1;
for (int factor : tableGcd.keySet()) {
int exp = tableGcd.get(factor);
for (int i = 0; i < exp; i++) {
gcd *= factor;
}
}
return gcd;
}
public static void main(String[] args) {
int a = 105;
int b = 180;
int gcd = calcGcd(a, b);
System.out.println(a + " と " + b + " の最大公約数は " + gcd);
}
}
コード例の解説
factorize
メソッドは、素因数分解の時と全く同じなので、解説を割愛します。
calcGcd
メソッドについてのみ解説します。
まずは、整数a
を渡した時の連想配列tableA
と、整数b
を渡した時の連想配列tableB
下記の通りです。
tableA = {3=1, 5=1, 7=1}
tableB = {2=2, 3=2, 5=1}
- 連想配列
tableGcd
を初期化します。 - 拡張
for
文により、連想配列tableA
の1つ目のKey=3
を、変数prime
に代入します。 - 連想配列
tableA
のKey=3
に対応するValue=1
を変数exp
に代入します。 -
if
文の条件式の連想配列tableB
に変数prime=3
というKey
が含まれているか、を満たすので、 -
tableA
のKey=3
に対応するValue=1
が代入された変数exp
と、tableB
のKey=3
に対応するValue=2
を比較して小さい方の1
を、変数exp
に代入して更新します。 - 連想配列
tableGcd
に、3=1
を代入します。 - 拡張
for
文により、連想配列tableA
の2つ目のKey=5
を、変数prime
に代入します。 - 連想配列
tableA
のKey=5
に対応するValue=1
を変数exp
に代入します。 -
if
文の条件式の連想配列tableB
に変数prime=5
というKey
が含まれているか、を満たすので、 -
tableA
のKey=5
に対応するValue=1
が代入された変数exp
と、tableB
のKey=5
に対応するValue=1
を比較して小さい方の1
を、変数exp
に代入して更新します。 - 連想配列
tableGcd
に、5=1
を代入します。 - 拡張
for
文により、連想配列tableA
の最後のKey=7
を、変数prime
に代入します。 - 連想配列
tableA
のKey=7
に対応するValue=1
を変数exp
に代入します。 -
if
文の条件式の連想配列tableB
に変数prime=7
というKey
が含まれているか、を満たさないので、if
文を抜けます。そして、拡張for
文も抜けます。
この時の連想配列tableGcd
は、下記の通りです。{3=1, 5=1}
- 変数
gcd
を1
で初期化します。 - 拡張
for
文により、連想配列tableGcd
の1つ目のKey=3
を、変数factor
に代入します。 - 連想配列
tableGcd
のKey=3
に対応するValue=1
を変数exp
に代入します。 -
for
文で1回だけループして、 - 変数
gcd
を3
に更新します。 - 拡張
for
文により、連想配列tableGcd
の最後のKey=5
を、変数factor
に代入します。 - 連想配列
tableGcd
のKey=5
に対応するValue=1
を変数exp
に代入します。 -
for
文で1回だけループして、 - 変数
gcd
を15
に更新し、拡張for
文を抜けます。 - 戻り値として変数
gcd
を返します。
最小公倍数
整数a
と整数b
の最小公倍数は、お互いの素因数について指数の最大値を取ることで求めることができます。
コード例
import java.util.*;
public class Main {
// 素因数分解
// 整数 a 及び b を受け取り、素因数分解をおこなって (素因数=個数) の連想配列を返す
static HashMap<Integer, Integer> factorize(int n) {
HashMap<Integer, Integer> primes = new HashMap<>();
for (int i = 2; i * i <= n; i++) {
if (n % i > 0) {
continue;
}
int exp = 0;
while (n % i == 0) {
exp++;
n /= i;
}
primes.put(i, exp);
}
if (n != 1) {
primes.put(n, 1);
}
return primes;
}
// 連想配列 primes を受け取り、最小公倍数を返す
static int calcGcd(int a, int b) {
HashMap<Integer, Integer> tableA = factorize(a);
HashMap<Integer, Integer> tableB = factorize(b);
HashMap<Integer, Integer> tableLcm = tableA;
for (int prime : tableB.keySet()) {
int exp = tableB.get(prime);
if (tableA.containsKey(prime)) {
exp = Math.max(exp, tableA.get(prime));
tableLcm.put(prime, exp);
}
tableLcm.put(prime, exp);
}
int lcm = 1;
for (int factor : tableLcm.keySet()) {
int exp = tableLcm.get(factor);
for (int i = 0; i < exp; i++) {
lcm *= factor;
}
}
return lcm;
}
public static void main(String[] args) {
int a = 36;
int b = 60;
int gcd = calcGcd(a, b);
System.out.println(a + " と " + b + " の最大公約数は " + gcd);
}
}
コード例の解説
下記の部分だけ解説します。
static int calcGcd(int a, int b) {
HashMap<Integer, Integer> tableA = factorize(a);
HashMap<Integer, Integer> tableB = factorize(b);
HashMap<Integer, Integer> tableLcm = tableA;
for (int prime : tableB.keySet()) {
int exp = tableB.get(prime);
if (tableA.containsKey(prime)) {
exp = Math.max(exp, tableA.get(prime));
tableLcm.put(prime, exp);
}
tableLcm.put(prime, exp);
}
}
まずは、連想配列tableA
と連想配列tableB
及び連想配列tableLcm
下記の通りです。
tableA = {2=2, 3=2}
tableB = {2=2, 3=1, 5=1}
tableLcm = {2=2, 3=2}
- 拡張
for
文により、連想配列tableB
の1つ目のKey=2
を、変数prime
に代入します。 - 連想配列
tableB
のKey=2
に対応するValue=2
を変数exp
に代入します。 -
if
文の条件式の連想配列tableA
に変数prime=2
というKey
が含まれているか、を満たすので、 -
tableB
のKey=2
に対応するValue=2
が代入された変数exp
と、tableA
のKey=2
に対応するValue=2
を比較して大きい方の2
を、変数exp
に代入して更新します。 - 連想配列
tableGcd
に、2=2
を代入します。 - 拡張
for
文により、連想配列tableB
の2つ目のKey=3
を、変数prime
に代入します。 - 連想配列
tableB
のKey=3
に対応するValue=1
を変数exp
に代入します。 -
if
文の条件式の連想配列tableA
に変数prime=3
というKey
が含まれているか、を満たすので、 -
tableB
のKey=3
に対応するValue=1
が代入された変数exp
と、tableA
のKey=3
に対応するValue=2
を比較して大きい方の2
を、変数exp
に代入して更新します。 - 連想配列
tableGcd
に、3=2
を代入します。 - 拡張
for
文により、連想配列tableB
の最後のKey=5
を、変数prime
に代入します。 - 連想配列
tableB
のKey=5
に対応するValue=1
を変数exp
に代入します。 -
if
文の条件式の連想配列tableA
に変数prime=5
というKey
が含まれているか、を満たさないので、if
文を抜けます。そして、拡張for
文も抜けます。 - 連想配列
tableGcd
に、5=1
を代入します。
この時の連想配列tableGcd
は、下記の通りです。tableLcm = {2=2, 3=2, 5=1}
Discussion