본문 바로가기

알고리즘/SWEA

7854. 최약수

[1. 정의]

  • 최약수: 앞에 어떤 숫자를 붙여도 자기 자신을 약수 갖는 수.
    • 예제
      • 2 앞에 어떤 수를 붙여도 해당 수는 2를 약수로 갖는다.
        • 12
      • 5 앞에 어떤 수를 붙여도 해당 수는 5를 약수로 갖는다.
        • 38275

[2. 요구 사항]

  • 임의의 숫자 X 가 있을 때, X 보다 작거나 같은 최약수의 개수
    • X 의 범위는 [1, 10^9]

[3. 해결 방법]

주어진 조건을 만족하는 수를 다음과 표현 할 수 있다.

T = (R+X)

T % X == 0

  • X = a*10^N + b*10^(N-1) + ... + z*10^0
    • 각 계수는 모두 0 이 아닌 자연수
    • N < 9 인 경우 0 < [a ~ z]  < 10
    • N == 9 인 경우, a == 1 이고 [b ~ z] 는 모두 0
  • R = a`*10^(N+1) + b`*10^(N+2) + ...
    • 각 계수는 모두 0 이 아닌 자연수
    • 0 < [a` ~ ] < 10

N == 0 인 경우,

  • 1 <= (X = z) < 10
  • R = 10a` + 100b` + ...
  • T = (10a` + 100b` + ... ) + z
  • X 가 1, 2, 5 인 경우 R 과 공약수를 갖게 되어 나누어 떨어지게 된다.

N == 1 인 경우,

  • 10 <= (X = (10y + z)) < 100
  • R = 100a` + 1000b` + ...
  • X 가 10, 20, 25, 50 인 경우 R 과 공약수를 갖게 됨.

N == 2 인 경우

  • 100 <= (X = (100x + 10y + z)) < 1000
  • R = 1000a` + 10000b` + ...
  • X 가 100, 125, 200, 250, 500 인 경우 R 과 공약수를 갖게 됨.

결과적으로 N 을 X 의 digit 개수라 할 때,

10^(N+1) 의 공약수 중 X 보다 작거나 같은 값들이 최약수가 된다고 볼 수 있다.

 

[4. 코드]

static vector<int> table[10];

static void table_init()
{
	table[0].push_back(1);
	table[0].push_back(2);
	table[0].push_back(5);

	table[1].push_back(10);
	table[1].push_back(20);
	table[1].push_back(25);
	table[1].push_back(50);

	table[2].push_back(100);
	table[2].push_back(125);
	table[2].push_back(200);
	table[2].push_back(250);
	table[2].push_back(500);

	for (int i = 3; i < 9; i++)
	{
		int j = i - 1;
		for (int idx = 0; idx < table[j].size(); idx++)
		{
			table[i].push_back(table[j][idx] * 10);
		}
	}

	table[9].push_back(1000000000);
}

static int digit_len(int n)
{
	int div = 10, ret = 1;

	while (n / div)
	{
		div *= 10;
		ret += 1;
	}

	return ret;
}

static int solution(void)
{
	int N, len, ret = 0, i;
	cin >> N;

	len = digit_len(N);
	
	for (i = 0; i < len - 1; i++)
		ret += table[i].size();

	for (int idx = 0; idx < table[i].size() && N >= table[i][idx]; idx++)
		ret += 1;

	return ret;
}

table_init() 은 main()에서 먼저 선행되어야 한다.

하드코딩한 감이 없지 않아 있지만, 일단은 pass가 되어서 괜찮은 것 같다.

내가 이 문제를 해결한 방법은 아래와 같다.

 

먼저 len(N)을 N의 길이라 하겠다. len(100) = 3, len(2) = 1 이런 느낌이다.

그래서 문제에서 요구하는 값을 구하려면 아래와 같아야 한다.

(aaaaaa10^(len(N)) + N) / N 이 나누어 떨어져야하고, 이렇게 되기 위해

N은 10, 100, 1000 ... 등의 약수여야 한다.

다만, 몇가지 제한이 있는데, 

N이 100 = {1, 2, 4, 5, 10, 20, 25, 50, 100} 이라면

될 수 있는 값은 1 < len(N) < 3 인 것만 된다는 것이다.

그래서 이 중 10, 20, 25, 50 만 문제에서 요구하는 값이 될 수 있는 것이다.

 

그래서 이러한 규칙을 찾으면 아래와 같다.

 

1, 2, 5 - a

10, 20, 25, 50 - b

100, 125, 200, 250, 500 - c

1000, 1250, 2000, 2500, 5000 - d

...

 

a 에서 b로 b에서 c로 넘어갈때 각 값의 10 씩 곱해서 넘어가면 되는데,

이를 2로 나누어서 중복된 값이 없으면 추가하고 있으면 그냥 넘어가는 식이다.

이 부분을 table_init() 에서 하드코딩해서 넘어 갔다.

d 이 후는 2로 나누면 이미 중복된 값이 있기 때문에 굳이 이 부분을 신경쓰기 않아도 된다.

또 한 그 값들이 오름차순으로 정렬된다.

'알고리즘 > SWEA' 카테고리의 다른 글

7964  (0) 2021.10.31
7965  (0) 2021.10.31
7584  (0) 2021.10.31
7732  (0) 2021.10.31
7853  (0) 2021.10.31