숫자나라 기사단의 각 기사에게는 1번부터
number
까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다.
각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다.
예를 들어, 15번으로 지정된 기사단원은 15의 약수가 1, 3, 5, 15로 4개 이므로, 공격력이 4인 무기를 구매합니다. 만약, 이웃나라와의 협약으로 정해진 공격력의 제한수치가 3이고 제한수치를 초과한 기사가 사용할 무기의 공격력이 2라면, 15번으로 지정된 기사단원은 무기점에서 공격력이 2인 무기를 구매합니다. 무기를 만들 때, 무기의 공격력 1당 1kg의 철이 필요합니다. 그래서 무기점에서 무기를 모두 만들기 위해 필요한 철의 무게를 미리 계산하려 합니다.
기사단원의 수를 나타내는 정수number
와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수limit
와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수power
가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.
- 1 ≤
number
≤ 100,000- 2 ≤
limit
≤ 100- 1 ≤
power
≤ limit
- 입출력 예 #1 : 1부터 5까지의 약수의 개수는 순서대로 [1, 2, 2, 3, 2]개입니다. 모두 공격력 제한 수치인 3을 넘지 않기 때문에 필요한 철의 무게는 해당 수들의 합인 10이 됩니다. 따라서 10을 return 합니다.
- 입출력 예 #2 : 1부터 10까지의 약수의 개수는 순서대로 [1, 2, 2, 3, 2, 4, 2, 4, 3, 4]개입니다. 공격력의 제한수치가 3이기 때문에, 6, 8, 10번 기사는 공격력이 2인 무기를 구매합니다. 따라서 해당 수들의 합인 21을 return 합니다.
✅ 처음에는 1부터
number
까지 모든 수에 대하여 1부터 특정 수에 대해 나머지 연산을 수행하여 일일이 약수를 구하는 로직을 생각했는데,number
의 범위가 10만이라 백 퍼 시간 초과가 뜰 것 같아서 제곱근을 활용하였다.
제곱근까지만 나머지 연산을 수행해 약수를 구해도, 그 이후의 약수들은 어차피 제곱근 이전의 약수들과 짝을 이루기 때문에 애초에 약수를 찾게 되면 제곱근 이후 짝까지 생각하여 개수를 2개씩 증가시켰다. 그런데, 제곱근 당사자의 경우에는 짝 없이 본인 혼자이므로, 제곱근에 해당하는 경우에는 다시 개수를 하나 빼주었다.
제곱근을 사용하니 모든 테스트 케이스를 통과하였지만, 실행 시간을 보니 뭔가 찝찝한 느낌이 들었다,, 뭔가 이게 최선이 아닌 느낌,,?
class Solution {
public int solution(int number, int limit, int power) {
int answer = 0;
for(int i=1;i<=number;i++) {
int cnt = 0;
for(int j=1;j<=(int)Math.sqrt(i);j++) {
if(i % j == 0) {
cnt += 2;
if(j == i / j) cnt--;
}
}
System.out.println(cnt);
if(cnt > limit) answer += power;
else answer += cnt;
}
return answer;
}
}
➕ 다른 사람의 코드 : 모든 수에 대한 약수를 일일이 구하는 것이 아닌, 1부터
number
까지의 약수의 개수를 저장하는 배열count
를 생성하여 1부터number
까지의 수를 약수로 가지는 수의count[i]
를 1씩 증가시키는 원리?인 것 같다.
내 코드는(1~number) 반복 -> 각 수의 제곱근까지 반복하며 약수 구하기 -> 나머지 연산 할 때마다 조건 판별
의 로직이여서 중첩 for문에 중첩 if문까지 난리법석 코드였는데 이 코드는(1~number) 반복 -> 해당 수를 약수로 가지는 수만 개수 증가
로직이다보니 반복이나 판별의 횟수가 훨씬 줄어들게 되었다! 그 결과 세 자리를 남발하던 실행 횟수가 두 자리, 혹은 한 자리대로 확 줄게 되었다 ㄷㄷ,,
class Solution {
public int solution(int number, int limit, int power) {
int[] count = new int[number + 1];
for (int i = 1; i <= number; i++) {
for (int j = 1; j <= number / i; j++) {
count[i * j]++;
}
}
int answer = 0;
for (int i = 1; i <= number; i++) {
if (count[i] > limit) {
answer += power;
} else {
answer += count[i];
}
}
return answer;
}
}