December 17, 2018
| 시간 제한 | 메모리 제한 |
|---|---|
| 2초 | 512MB |
어떤 수 X가 1보다 큰 제곱수로 나누어 떨어지지 않을 때, 제곱ㄴㄴ수라고 한다.
제곱수는 정수의 제곱이다. min과 max가 주어지면,
min과 max를 포함한 사이에 제곱ㄴㄴ수가 몇 개 있는지 출력한다.
첫째 줄에 min과 max가 주어진다.
min은 1보다 크거나 같고, 1,000,000,000,000보다 작거나 같은 자연수이고,
max는 min보다 크거나 같고, min+1,000,000보다 작거나 같은 자연수이다.
첫째 줄에 [min,max]구간에 제곱ㄴㄴ수가 몇 개인지 출력한다.
1 1071보다 큰 재곱수로 나누어 떨어지지 않는 수를 의미한다.
1에서 10사이의 제곱ㄴㄴ수는 1,2,3,5,6,7,10이 있다.
4는 제곱수인 4스스로 나누어 떨어 지기 때문에 제곱ㄴㄴ수가 아니고
8은 제곱수인 4로 나누어 떨어 지기 때문에 제곱ㄴㄴ수가 아니며
9는 제곱수인 9스스로 나누어 떨어지기 때문에 아니다.
min과 max의 최댓값은 1조다.
max - min의 값의 최대는 100만이다.
1은 무조건 제곱ㄴㄴ수다.[min(1), max(10)]
초기의 num리스트
[True, True, True, True, True , True, True, True, True, True]초기의 count값은 10이다.
첫 제곱수인 4부터 반복
square변수의 값은 4i변수의 값은 0idx변수의 값은 -1로 조건 Falsei변수의 값 증가로 현재 i의 값은 1idx변수의 값은 3idx >= 0 and num[idx]가 Truecount변수 감소, num[idx]값 False로 변경
4를 찾은 경우i변수의 값 증가로 현재 i의 값은 2idx변수의 값은 77번 8번과정과 동일
8을 찾은 경우i변수의 값 증가로 현재 i의 값은 3
square * i = 12로 안쪽 loop조건 False로 탈출현재 num리스트의 상태
[True, True, True, False, True , True, True, False, True, True]제곱수 4의 배수인 4와 8이 걸러졌다.
현재 count의 값은 8이다.
다음 바깥쪽 loop진행
현재 n의 값은 3 제곱수 9로 반복
square변수의 값은 9i변수의 값은 0idx변수의 값은 -1로 조건 Falsei변수의 값 증가로 현재 i의 값은 1idx변수의 값은 8idx >= 0 and num[idx]가 Truecount변수 감수, num[idx]값 False로 변경
9를 찾은 경우i변수의 값 증가로 현재 i의 값은 2
square * i = 18로 안쪽 loop의 조건 False로 탈출현재 num리스트의 상태
[True, True, True, False, True , True, True, False, False, True]제곱수 9의 배수인 9 걸러졌다.
현재 count의 값은 7이다.
현재 n의 값은 4로 바깥쪽 loop의 조건인
n ** 2 <= max를 n ** 2의 값이 16으로 max값인 10보다
커지게 되므로 바깥쪽 loop도 탈출하며 알고리즘 종료
[1, 10]사이의 제곱ㄴㄴ수는 7개가 된다.
글로만 보니 좀 복잡한거 같아 표로 그림을 그려보도록 하겠다.
| 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|
| 6 | 7 | 8 | 9 | 10 |
다음과 같은 초기의 배열이 있다고 하자.
여기에서 제곱수 4의 배수들을 모두 지워주는 것이다.
| 1 | 2 | 3 | X | 5 |
|---|---|---|---|---|
| 6 | 7 | X | 9 | 10 |
4의 배수를 모두 지운 후 다음 제곱수인
9의 배수를 모두 지워 주면 된다.
| 1 | 2 | 3 | X | 5 |
|---|---|---|---|---|
| 6 | 7 | X | X | 10 |
이렇게 되면 제곱ㄴㄴ수만 남게 된다.
소수 판별 알고리즘인 에라토스테네스의 체와 비슷하다.
에라토스테네스의 체를 잘 모르면 여기를 참고하면 된다.
import sys
min, max = map(int, sys.stdin.readline().split())
num = [True for _ in range(min, max + 1)]
count = len(num)
n = 2
while n ** 2 <= max:
square = n ** 2
i = min // square
while square * i <= max:
idx = square * i - min
if idx >= 0 and num[idx]:
count -= 1
num[idx] = False
i += 1
n += 1
print(count)
느리고.. 느리고.. 느렸다..
채점하는데도 진짜 2분은 더 걸린 것 같다..
솔직히 엄청 금방 풀 줄 알았다..
1977번 완전제곱수 문제처럼 Pythonic하게도 짜봐야지~ 했는데…
시간 초과, 메모리 초과의 벽에서 무너졌다😓😓
최근 푼 문제들 중에 제일 힘들었다…😵😵
✅ 코드는 [여기]에서 확인할 수 있다.