약수 알고리즘(Divisor Algorithm)

약수(divisor)를 구하는 다양하고 효율적인 방법을 알아보자.


약수의 성질

임의의 정수 N의 약수 n(n ∈ N) 에서 n은 다음 성질들을 갖는다.

  • ±1 ∈ N
  • ±n ∈ N
  • N % n = 0

Code 1_1

약수를 구하는 가장 기본적인 코드

public static void main(String[] args) {

	Scanner sc = new Scanner(System.in);
	int N = sc.nextInt();

	for(int i=1;i<=N;i++)
		if(N%i==0) System.out.println(i);
}

Code 1_2

Code1_1은 1부터 N까지 탐색하여 약수를 판별한다. Code1_2에서는 N의 약수중에 최대값은 N이고 그 다음의 최대값이 될 수 있는 값은 아무리 크더라도 N/2라는 점을 사용하였다.

for (int i = 1; i <= N / 2; i++)
	if (N % i == 0)
		System.out.println(i);
System.out.println(N);

반복 횟수가 절반이 되어 효율을 높일 수 있다.


Code 2_1

약수의 개수를 구하는 기본적인 코드, Code1_2와 동일하다.

public static void main(String[] args) {

	Scanner sc = new Scanner(System.in);

	int N = sc.nextInt();
	int cnt = 1;

	for (int i = 1; i <= N / 2; i++)
		if (N % i == 0)
			cnt++;

	System.out.println(cnt);

}

Code 2_2

1부터 n까지 정수 중에 약수의 개수가 가장많은 정수를 구할때는 Code2_1 기본형을 통해 간단하게 구현할 수 있다.

public class Main {

	public final static int MAXNUM = 101;
	public static int[] arr = new int[MAXNUM];

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		for (int i = 1; i < MAXNUM; i++) {
			int cnt = 1;

			for (int j = 1; j <= i / 2; j++)
				if (i % j == 0)
					cnt++;

			arr[i] = cnt;
		}
	}
}

위 알고리즘은 n*(n/2)의 시간 복잡도를 갖는다.


Code 2_3

코드 2_2는 정수 n값이 커질수록 부담이된다. 1부터 n까지의 약수의 개수를 구하는 상황에서 배수를 응용하면 무의미하게 반복하는 과정을 줄일 수 있다.

public class Main {

	public final static int MAXNUM = 101;
	public static int[] arr = new int[MAXNUM];

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		for(int i=1;i<MAXNUM;i++){
			for(int j=1;j<MAXNUM/i;j++){
				arr[i*j]++;
			}
		}
	}
}

n, n/2, n/3 ···· n/n 만큼 반복을 수행하여 시간복잡도를 줄일 수 있다.


백준 2986 파스칼

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		int n = sc.nextInt();
		int result = 1;

		for (int i = n / 2;; i--) {
			if (n == 1) break;
			if (n % i == 0) {
				result = n - i;
				break;
			}
		}

		System.out.println(result);
	}
}

Comment

약수에 대한 알고리즘은 계속 추가할 예정.