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 10
7
1
보다 큰 재곱수로 나누어 떨어지지 않는 수를 의미한다.
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
변수의 값은 4
i
변수의 값은 0
idx
변수의 값은 -1
로 조건 False
i
변수의 값 증가로 현재 i
의 값은 1
idx
변수의 값은 3
idx >= 0 and num[idx]
가 True
count
변수 감소, num[idx]
값 False
로 변경
4
를 찾은 경우i
변수의 값 증가로 현재 i
의 값은 2
idx
변수의 값은 7
7번 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
변수의 값은 9
i
변수의 값은 0
idx
변수의 값은 -1
로 조건 False
i
변수의 값 증가로 현재 i
의 값은 1
idx
변수의 값은 8
idx >= 0 and num[idx]
가 True
count
변수 감수, 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하게도 짜봐야지~ 했는데…
시간 초과, 메모리 초과의 벽에서 무너졌다😓😓
최근 푼 문제들 중에 제일 힘들었다…😵😵
✅ 코드는 [여기]에서 확인할 수 있다.