🎯
【Java】素因数分解と約数の個数
素因数分解
180
を素因数分解すると、
となります。
問題
n = 180
を素因数分解した時の結果を標準出力に出力せよ。
答え
2
2
3
3
5
コード例
import java.util.*;
public class Main {
// 整数 n=180 を受け取り、素因数分解をおこなって (素因数=指数) の連想配列を返す
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;
}
public static void main(String[] args) {
int n = 180;
HashMap<Integer, Integer> table = factorize(n);
for(int prime : table.keySet()){
int exp = table.get(prime);
for(int i = 0; i < exp; i++){
System.out.println(prime);
}
}
}
}
コード例の解説
mainメソッドのn = 180
から順を追っていきたいと思います。
但し、標準出力に出力する過程の解説は割愛します。
-
n = 180
と定義します。 -
factorize
メソッドを呼び出し、実引数としてn
を渡します。 -
factorize
メソッド内で、primes
という連想配列を初期化します。 -
2
から√n
までループするfor
文を定義します。 -
if
文の条件式が、n
をi
で割った時の余りが0より大きい場合は、となっており、これは、結局のところn
を割り切れないi
の場合ということです。 - 上記が
true
なら、continue
により、i
を1
増やして、for
文を進めます。 -
n
を割り切れるi
の場合は、変数exp
を0
で初期化します。(exp → exponent → 指数) -
while
文の条件式n=180
をi=2
で割ると余りは0
を満たすので、 - 変数
exp
を1
に更新します。 -
n=90
に更新します。 -
while
文の条件式n=90
をi=2
で割ると余りは0
を満たすので、 - 変数
exp
を2
に更新します。 -
n=45
に更新します。 -
while
文の条件式n=45
をi=2
で割ると余りは0
を満たさないので、while
文を抜けます。 - 連想配列
primes
に2=2
を代入します。 -
i
を1
増やして、n=45
をi=3
は割り切れるので、if
文には入らず、 - 変数
exp
を0
で初期化します。 -
while
文の条件式n=45
をi=3
で割ると余りは0
を満たすので、 - 変数
exp
を1
に更新します。 -
n=15
に更新します。 -
while
文の条件式n=15
をi=3
で割ると余りは0
を満たすので、 - 変数
exp
を2
に更新します。 -
n=5
に更新します。 -
while
文の条件式n=5
をi=3
で割ると余りは0
を満たさないので、while
文を抜けます。 - 連想配列
primes
に3=2
を代入します。 - 以降、
i
を1
増やしていき、i
=4
~13
(√180
は約13.4
)までfor
文をループしますが、どれも割り切れないため、continue
により、for
文を進めるめることになり、このfor
文からも抜けます。 -
if
文の条件式n=5 != 1
を満たすので、 - 連想配列
primes
に5=1
を代入します。 - 呼び出し元に戻り値として連想配列
primes
を返します。
この時の連想配列primes
は、下記の通りです。{2=2, 3=2, 5=1}
約数の個数
180
の約数の個数は、素因数分解した各素因数の指数に1を足してからそれぞれを掛け合わせることで求めることができます。
問題
n = 180
の約数の個数を標準出力に出力せよ。
答え
18
コード例
import java.util.*;
public class Main {
// 素因数分解のものと全く同じ
// 整数 n=180 を受け取り、素因数分解をおこなって (素因数=指数) の連想配列を返す
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 calcNumOfPrimeFactors(int n) {
HashMap<Integer, Integer> primes = factorize(n);
int numOfPrimeFactors = 1;
for (int num : primes.values()) {
numOfPrimeFactors *= (num + 1);
}
return numOfPrimeFactors;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int numOfPrimeFactors = calcNumOfPrimeFactors(n);
System.out.println(numOfPrimeFactors);
}
}
コード例の解説
factorize
メソッドは、素因数分解の時と全く同じなので、解説を割愛します。
calcNumOfPrimeFactors
メソッドについてのみ解説します。
まずは、連想配列primes
は、下記の通りです。
{2=2, 3=2, 5=1}
- 変数
numOfPrimeFactors
を1
で初期化します。 - 拡張
for
文により、連想配列primes
の1つ目のValue=2
を、変数num
に代入します。 - 変数
numOfPrimeFactors
を3
で更新します。 - 拡張
for
文により、連想配列primes
の2つ目のValue=2
を、変数num
に代入します。 - 変数
numOfPrimeFactors
を9
で更新します。 - 拡張
for
文により、連想配列primes
の3つ目のValue=1
を、変数num
に代入します。 - 変数
numOfPrimeFactors
を18
で更新します。 - 呼び出し元に戻り値として変数
numOfPrimeFactors
を返します。
Discussion