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

 

2023번: 신기한 소수

수빈이가 세상에서 가장 좋아하는 것은 소수이고, 취미는 소수를 가지고 노는 것이다. 요즘 수빈이가 가장 관심있어 하는 소수는 7331이다. 7331은 소수인데, 신기하게도 733도 소수이고, 73도 소수이고, 7도 소수이다. 즉, 왼쪽부터 1자리, 2자리, 3자리, 4자리 수 모두 소수이다! 수빈이는 이런 숫자를 신기한 소수라고 이름 붙였다. 수빈이는 N자리의 숫자 중에서 어떤 수들이 신기한 소수인지 궁금해졌다. N이 주어졌을 때, 수빈이를 위해 N자리

www.acmicpc.net

http://koistudy.net/?mid=prob_page&NO=688&SEARCH=0

 

KOISTUDY

 

koistudy.net

 

 

에라토스테네스로는 해결이 안된다

 

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
58
59
60
61
62
#include <iostream>
/*
 한 자릿수 중 소수는 2, 3, 5, 7 밖에 없다. 따라서 제일 높은 자릿수의 값은 2, 3, 5, 7만 될 수 있다. 
 (∵오른편 절단 가능 소수이므로)
 
 2. 두 자릿수 이상 넘어가면서 마지막 자릿수 값은 짝수가 될 수 없고(∵2의 배수),
 마찬가지로 5도 될 수 없다(∵5의 배수). 따라서 남는 숫자는 1, 3, 7, 9만 남게 된다. 
 10개의 자릿수를 모두 다 탐색하는 것에 비해 가짓수가 현저히 줄어들게 됨으로 탐색이 빨라진다. (가지치기) 
 
 3. 자릿값을 늘려갈 때 현재 숫자가 소수인지 판별하여 소수인 숫자에만 뒤에 1, 3, 7, 9를 붙여가며 늘려간다. 
 숫자가 커지면 소수 판별에도 시간이 많이 걸리므로 시간을 줄이기 위해 O(sqrt(n))소수 판별 알고리즘을 사용한다.
*/
int n, cnt;
 
int is_prime(int x)
{
    if (x < 2)
    {
        return 0;
    }
    for (int i = 2; i * i <= x; ++i)
    {
        if (x % i == 0)
        {
            return 0;
        }
    }
    return 1;
}
 
void func(int num, int len)
{
    if (len == n)
    {
        if (is_prime(num))
        {
            ++cnt;
            std::cout << num << '\n';
        }
        return;
    }
    else
    {
        if (is_prime(num))
        {
            func(num * 10 + 1, len + 1);
            func(num * 10 + 3, len + 1);
            func(num * 10 + 7, len + 1);
            func(num * 10 + 9, len + 1);
        }
    }
}
 
int main()
{
    std::cin >> n;
    func(21);
    func(31);
    func(51);
    func(71);
    //std::cout << cnt;
}
cs

 

이게 놀라운게 백준은 메모리로 날려버린다지만 koi 저지같은경우 메모리 허용이 되는데, 이 때 에라토스테네스 쓰면 시간초과가 난다.

 

탐색영역의 배제 방식이 dp보다 빠른 경우가 생길수 있다는걸 보여주는 예

 

 

더 괜찮은 소수 판별

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int is_prime(int x)
{
    if (x < 2)
    {
        return 0;
    }
    for (int i = 3; i * i <= x; i += 2)
    {
        if (x % i == 0)
        {
            return 0;
        }
    }
    return 1;
}
cs

x가 2라면 바로 1을 리턴한다.

 

그 외의 경우라면 계산량을 줄일 수 있다

'알고리즘' 카테고리의 다른 글

koi : 앱(small)  (0) 2020.05.01
koi : 최소합  (0) 2020.04.28
koi : 리모콘(dfs, bfs)  (0) 2020.04.24
백준 10971 : 외판원 순회 2 & koi : 연구활동 가는길  (0) 2020.04.24
백준 2615 : 오목  (0) 2020.04.20

+ Recent posts