포스트

1990 소수인펠린드롬

소수이면서 펠린드롬인 숫자를 찾는 문제

시간 복잡도에 주의할 것

https://www.acmicpc.net/problem/1990

1. 문제


간단 설명

a부터 b사이의 숫자 중에서

펠린드롬이면서(거꾸로해도 같은 문자열), 소수인 숫자를 찾아 출력하기

2. 문제 분석


필요변수

시작 a, 끝 b

펠린드롬인지 판별할 IsPelidrome 함수

소수 판별할 IsPrime 함수

주의점

소수를 구할 때, 시간 복잡도에 주의한다

5 <= a, b <= 100,000,000 이므로

펠린드롬 계산은 얼마 걸리지 않아 패스

소수 계산에서 시간 복잡도가 상당함

쌩 노가다로 소수를 계산해버리면

O(N^2) 이므로 10^18. 1초를 넘어버림

에라토스테네스의 체를 이용하면 쉽게 구할 수 있다

알고리즘

1
2
3
4
5
6
7
8
1. a, b를 입력받고
2. 범위내 숫자 i가 펠린드롬인지 체크하고, 맞다면 소수 판별을 진행한다
    - if문에서 누가 먼저 오느냐에 따라 수행시간이 달라짐.
    - 펠린드롬을 먼저 체크하고 소수 판별을 진행할것인가, 아님 반대로?
    2-1. 펠린드롬 체크. 문자열을 반으로 쪼개서 끝부분부터 일치하는지 체크
    2-2. 소수 체크. 숫자를 2~sqrt(n)까지 숫자로 나눠본다. 나눠지면 소수 아님
    2-3. 두 조건을 만족했다면 숫자를 출력 
3. 다 출력했다면 -1 출력하고 종료
  • 실제로 돌려보면 소수이면서, 펠린드롬인 숫자는 10,000,000 을 넘어선 나타나지 않는다 그래서 for문에서 이 이후의 숫자는 보지 않는걸로 처리해버림

https://www.acmicpc.net/board/view/1065

  • 처음에는 에라토스테네스의 체를 1~N 까지 구해놓고 시작했으나, 시간초과남 (체를 채우는 과정에서 10^18번 수행)

왜 에라토스테네스 체를 sqrt(N)까지만 구하면 되는지 증명

3. 소스코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <string>
#include <cmath>

using namespace std;

bool prime[1000000001] = { 0 };

// 펠린드롬 판별 함수
bool IsPelindrome(int num) {
	string tmp = to_string(num);
	// 한자리는 무조건 펠린드롬임
	if (tmp.size() == 1) {
		return true;
	}

	// 두자리부터는 체크 들어감
	int mid = tmp.length() / 2;

	for (int i = 0; i < mid; i++) {
		if (tmp[i] != tmp[tmp.size() - 1 - i]) {
			return false;
		}
	}

	return true;
}

// 소수 판별 함수
bool IsPrime(int num) {
	if (num < 2) return false;

	for (int i = 2; i <= sqrt(num); i++) {
		if (num % i == 0) return false;
	}

	return true;
}

int main() {
	freopen_s(new FILE*, "input.txt", "r", stdin);
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);

	int a, b;
	cin >> a >> b;
	// 소수이고 펠린드롬이라면 출력
	for (int i = a; i <= 10000000; i++) {
		if (i > b) break;
		if (IsPelindrome(i) && IsPrime(i)) {
			cout << i << endl;
		}
		
	}
	cout << -1;

}

에라토스테네스 체는 sqrt(n)까지만 구하면 된다… 기억해두기!

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.