백준 2023 - 신기한 소수
문제 설명
수빈이가 세상에서 가장 좋아하는 것은 소수이고, 취미는 소수를 가지고 노는 것이다. 요즘 수빈이가 가장 관심있어 하는 소수는 7331이다.
7331은 소수인데, 신기하게도 733도 소수이고, 73도 소수이고, 7도 소수이다. 즉, 왼쪽부터 1자리, 2자리, 3자리, 4자리 수 모두 소수이다! 수빈이는 이런 숫자를 신기한 소수라고 이름 붙였다.
수빈이는 N자리의 숫자 중에서 어떤 수들이 신기한 소수인지 궁금해졌다. N이 주어졌을 때, 수빈이를 위해 N자리 신기한 소수를 모두 찾아보자.
https://www.acmicpc.net/problem/2023
제한 사항


풀이
문제를 요약하면, N자리 수중 왼쪽부터 1자리, 2자리, ... N자리까지 모두 소수인 수를 구하는 것이다.
소수 판정 알고리즘에는 유명한 에라토스테네스의 체가 있다.
처음엔 이걸 활용하여 문제를 풀었더니 메모리 초과가 발생했다.
제한을 확인해 보니 메모리 제한이 4MB밖에 되지 않았다.
즉, 이는 활용할 수 없고 직접 소수를 판정해야 한다.
소수를 판정하는 것은 간단하다.
제곱근까지의 수중 x를 나누어 떨어지게 만드는 수가 있는지 확인하면 된다.
bool IsPrime(int x)
{
if (x == 1) return false;
for (int i = 2; i * i <= x; i++)
{
if (x % i == 0) return false;
}
return true;
}
그럼 이제, N자리수의 시작인 수부터 N+1 자릿수의 시작인 수까지 조건에 맞는 수를 찾으면 된다.
이때, 모든 수를 순회하면 시간초과가 발생한다.
조건을 이용하여 생각을 바꾸면 간단하게 풀 수 있다.
왼쪽부터 1자리, 2자리, ... N자리까지 모두 소수여야 한다.
즉, 수를 한 자리씩 늘려갔을 때 소수인 것들만 유지하면 된다는 뜻이다.
BFS를 통해 끝자리에 수를 더했을 때 소수인 것들은 큐에 다시 넣으면 된다.
그러면 큐에는 모두 소수인 수들만 유지가 될것이고 그 수가 N자리라면 정답에 포함시키면 된다.
while (!q.empty())
{
int current = q.front();
q.pop();
if (current >= target && current < limit)
{
answers.push_back(current);
continue;
}
for (int i = 0; i <= 9; i++)
{
int num = current * 10 + i;
if (IsPrime(num))
{
q.push(num);
}
}
}
전체 코드
#include <bits/stdc++.h>
using namespace std;
#define INPUT_OPTIMIZE cin.tie(NULL); cout.tie(NULL); ios::sync_with_stdio(false);
#define INF 2e9
using namespace std;
int N;
int prime[] = { 2, 3, 5, 7 };
bool IsPrime(int x)
{
if (x == 1) return false;
for (int i = 2; i * i <= x; i++)
{
if (x % i == 0) return false;
}
return true;
}
int main()
{
INPUT_OPTIMIZE;
cin >> N;
int target = pow(10, N - 1);
int limit = pow(10, N);
queue<int> q;
vector<int> answers;
for (int i = 0; i < 4; i++)
{
q.push(prime[i]);
}
while (!q.empty())
{
int current = q.front();
q.pop();
if (current >= target && current < limit)
{
answers.push_back(current);
continue;
}
for (int i = 0; i <= 9; i++)
{
int num = current * 10 + i;
if (IsPrime(num))
{
q.push(num);
}
}
}
for (auto& ans : answers)
{
cout << ans << "\n";
}
return 0;
}