🎯
【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