2023. 6. 24. 15:00ㆍ개발/👾 PS
1. 개념
알고리즘 문제에 자주 나오는 정수론 개념에는 '소수'와 '호제법'이 있다.
'소수' 관련 문제는 대부분 특정 범위 내에서 소수의 개수를 구하는 문제가 많이 출제된다.
[ 1 ] 소수
소수 : 1보다 큰 자연수 중 1과 자기 자신만을 약수로 가지는 수
n까지의 숫자 범위 내에서 소수를 찾는 방법 -> '에라토스테네스의 체'
< 에라토스테네스의 체 >
( 1 ) n만큼 일차원 리스트 생성
* 리스트의 값을 인덱스 값으로 초기화
( 2 ) 리스트에서 지워지지 않았다면 리스트를 탐색하면서 현재 선택된 숫자의 배수를 삭제
* 이때 현재 선택된 숫자는 삭제하지 않는다
( 3 ) 2에서부터 n의 제곱근까지 ( 2 )를 반복한 뒤 리스트에 남아있는 숫자를 출력
서로소 : 두 수의 공약수가 1 이외에 없는 관계
1~n과 서로소인 자연수의 개수를 각각 구하는 방법 -> 오일러 피 P(n)
< 오일러 피 >
( 1 ) n까지의 범위만큼 리스트 생성
* 리스트의 값을 인덱스 값으로 초기화
( 2 ) 현재 리스트의 값과 인덱스가 같으면 현재 선택된 숫자의 배수에 해당하는 수(K)에 대해
P(i) = P(i) - P(i) / K 를 수행
( 3 ) 2에서부터 리스트 끝까지 (2)를 반복
2. 문제 풀이
# 1 소수 구하기 - 백준 1929번
https://www.acmicpc.net/problem/1929
1929번: 소수 구하기
첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.
www.acmicpc.net
import sys
import math
input = sys.stdin.readline
m, n = map(int, input().split())
numlist = []
# 수의 범위만큼 리스트 생성
for i in range(n+1):
numlist.append(i)
numlist[1] = 0
# 소수 구하는 방법_1
for i in range(2, int(math.sqrt(n))+1): ##범위는 n의 제곱근까지
if numlist[i] != 0:
for j in range(i+1, n+1):
if numlist[j] % i == 0:
numlist[j] = 0
# 소수 구하는 방법_2
for i in range(2, int(math.sqrt(n)+1)):
if numlist[i] != 0:
for j in range(i+i, len(numlist), i): ## i(현재 선택한 수) 제외하고 i의 배수 제거
numlist[j] = 0
for i in range(m, n+1):
if numlist[i] != 0:
print(numlist[i])
* 처음에는 바깥 탐색 범위를 n/2 까지 했었는데 시간 초과가 나와서 탐색 범위를 n의 제곱근으로 낮추니까 풀렸다.
바깥 탐색 범위를 n의 제곱근까지만 해도 괜찮은 이유!
바깥 탐색 범위를 X라고 하면 전체 리스트에서 2부터 X의 배수들만 삭제한다는 뜻이다.
A = B * C 라고 했을 때 ( B와 C의 배수 A / A는 X보다 작거나 같다 / X = (X의 제곱근) * (X의 제곱근) )
B와 C는 항상 X의 제곱근보다 작다.
# 2 거의 소수 구하기
https://www.acmicpc.net/problem/1456
1456번: 거의 소수
어떤 수가 소수의 N제곱(N ≥ 2) 꼴일 때, 그 수를 거의 소수라고 한다. 두 정수 A와 B가 주어지면, A보다 크거나 같고, B보다 작거나 같은 거의 소수가 몇 개인지 출력한다.
www.acmicpc.net
# 3 소수 & 팰린드롬 수 중에서 최솟값 찾기
https://www.acmicpc.net/problem/1747
1747번: 소수&팰린드롬
어떤 수와 그 수의 숫자 순서를 뒤집은 수가 일치하는 수를 팰린드롬이라 부른다. 예를 들어 79,197과 324,423 등이 팰린드롬 수이다. 어떤 수 N (1 ≤ N ≤ 1,000,000)이 주어졌을 때, N보다 크거나 같고,
www.acmicpc.net
import sys
import math
input = sys.stdin.readline
n = int(input())
numlist = [0]*1100001
k = n
for i in range(2, len(numlist)):
numlist[i] = i
for i in range(2, int(math.sqrt(len(numlist)))+1):
if numlist[i] == 0:
continue
for j in range(i+i, len(numlist), i):
numlist[j] = 0
def Pal(i):
i = list(str(i))
if i == i[::-1]:
return True
else:
return False
while True:
a = numlist[k]
if a != 0:
if Pal(a):
print(a)
break
k += 1
계속 IndexError 나서 열 받아서 질문 게시판 찾아보니까 소수 찾는 범위를 110만까지 늘리라길래 그렇게 했더니 풀렸다....ㅎ 왜징??
# 4 제곱이 아닌 수 찾기 - 백준 1016번
https://www.acmicpc.net/problem/1016
1016번: 제곱 ㄴㄴ 수
어떤 정수 X가 1보다 큰 제곱수로 나누어 떨어지지 않을 때, 그 수를 제곱ㄴㄴ수라고 한다. 제곱수는 정수의 제곱이다. min과 max가 주어지면, min보다 크거나 같고, max보다 작거나 같은 제곱ㄴㄴ수
www.acmicpc.net
# 5 오일러 피 - 백준 11689번
https://www.acmicpc.net/problem/11689
11689번: GCD(n, k) = 1
자연수 n이 주어졌을 때, GCD(n, k) = 1을 만족하는 자연수 1 ≤ k ≤ n 의 개수를 구하는 프로그램을 작성하시오.
www.acmicpc.net
'개발 > 👾 PS' 카테고리의 다른 글
[유니온 파인드] 알고리즘 (0) | 2023.07.01 |
---|---|
[ 그래프 ] 자료구조 (0) | 2023.06.30 |
[ 그리디 ] 알고리즘 (1) | 2023.05.24 |
[ 파이 ∞ 조각을 가질거야 ] - 알고리즘 스터디 (1) | 2023.05.16 |
[ 기수 정렬 ] 알고리즘 (0) | 2023.03.19 |