[Programmers] Level1 : 기사단원의 무기
Question
Solution
- number까지의 약수의 개수를 구하고 limit를 적용하여 모두 합해야한다.
- 이중 for루프를 이용하여 1~number까지 약수의 수를 구하도록한다.
- count가 limit 보다 크면 power로 만들고 종료시 answer에 count를 더해준다.
주의! 약수를 구할땐 i % j == 0 이면 약수이지만 완전탐색시 O(N)의 시간복잡도를 가지기 때문에 시간초과가 발생한다.
따라서 제곱근까지 탐색하는 방법을 사용한다.
ex) i = 6 일때 약수는 1, 2, 3, 6 이다. (1일때와 2일때만 약수를 구하면 모두 구해지는 점을 이용한다.)
1 * 6, 2 * 3 이므로 나누어 떨어지때마다 count += 2를 해주되 예외가 있다.
i = 4 일경우 2 * 2 = 4가 되는 중복되는 수가 있기 때문에 해당 조건을 예외처리 해준다.
Cord
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 시간초과
int solution_TimeOver(int number, int limit, int power)
{
int answer = 0;
// number까지 순서대로 탐색
for (int i = 1; i <= number; ++i)
{
int count = 0; // i에 대한 약수의 수
for (int j = 1; j * j <= i; ++j)
{
if (i % j == 0) { ++count; }
}
// count가 limit 보다 크면 power로 제한
if (count > limit) { count = power; }
answer += count;
}
return answer;
}
// 정답
int solution(int number, int limit, int power)
{
int answer = 1; // 1의 약수는 항상 한 개
// 2부터 number까지 순서대로 탐색
for (int i = 2; i <= number; ++i)
{
int count = 0; // i에 대한 약수의 수
// 자신 i의 제곱근까지 구하면 됨
// 6 = 1 * 6, 2 * 3 -> 1, 2, 3, 6
for (int j = 1; j * j <= i; ++j)
{
if (j * j == i) { ++count; } // 제곱수 중복 예외처리
else if (i % j == 0) { count += 2; }
}
// count가 limit 보다 크면 power로 제한
if (count > limit) { count = power; }
answer += count;
}
return answer;
}
int main()
{
int number = 5;
int limit = 3;
int power = 2;
int answer = solution(number, limit, power);
cout << answer;
return 0;
}