백준 알고리즘 단계별로 풀어보기/약수, 배수와 소수

백준 알고리즘 2581번 소수 (C언어)

MNMNWVWV 2023. 3. 8. 20:54
728x90
반응형
실버Ⅴ

 

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

 

2581번: 소수

M이상 N이하의 자연수 중 소수인 것을 모두 찾아 첫째 줄에 그 합을, 둘째 줄에 그 중 최솟값을 출력한다.  단, M이상 N이하의 자연수 중 소수가 없을 경우는 첫째 줄에 -1을 출력한다.

www.acmicpc.net

 

 

 

 

 

풀이 방법

 

우선 이 문제는 M과 N을 입력받고, M과 N 사이의 수 중 소수를 찾아 그 소수들을 모두 합한 값과, 그 소수 중 가장 작은 값을 각각 출력하는 문제이다.

 

먼저 나의 경우 N의 값을 입력받으면서 배열의 크기가 최대 N으로 고정되기 때문에 10000의 원소를 갖는 배열을 만드는 방법이 아닌, 동적할당을 이용해 배열을 할당했다. 

만약 동적할당의 사용법을 모른다면 동적할당에 관한 글을 아래에 링크로 남겨놓겠다.

https://bakjoon-coding.tistory.com/24

 

[C언어 기초] 메모리 동적할당(malloc)

C언어는 정적할당과 동적할당 두 가지 할당 방법을 제공합니다. 정적할당은 프로그램이 실행될 때 메모리를 할당하고, 이후에는 할당된 메모리의 크기나 위치를 변경할 수 없습니다. 이와는 달

bakjoon-coding.tistory.com

 

 

소수를 구하는 방법의 경우, 에라토스테네스의 체 알고리즘을 이용해 소수를 구해보았다. 만약 에라토스테네스의 체 알고리즘을 잘 모른다면, 에라토스테네스의 체 알고리즘에 관한 글 역시 써 놓았다. 아래의 글을 보고 오면 된다.

https://bakjoon-coding.tistory.com/23

 

[알고리즘] 에라토스테네스의 체 알고리즘(C언어)

'에라토스테네스의 체' 란? '에라토스테네스의 체'란, 2부터 시작하는 양의 정수들 중에서 소수(prime number)인 것을 찾아내는 알고리즘 중 하나입니다. 이 알고리즘은 2부터 시작하여, 그 다음 소수

bakjoon-coding.tistory.com

 

소수를 구하고 난 후에는 소수 중 최솟값과 소수들의 합을 구하였다.

 

내 코드

 

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
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
 
void Seive_of_Eratosthenes(int *arr, int N);
 
int main(void) {
    
    int M, N, i, *arr = NULL, sum = 0, flag = 0, Prime_min;
 
    scanf("%d %d"&M, &N);
 
    arr = (int*)malloc((N+1* sizeof(int));
    if (arr == NULL)
        return -1;
 
    Seive_of_Eratosthenes(arr, N);
 
    for (i = M; i <= N; ++i) {
        if (arr[i] != 0) {
            //소수 중 최솟값
            if (flag == 0) {
                Prime_min = arr[i];
                flag = 1;
            }
            sum += arr[i];
        }
    }
 
    if (sum == 0)
        printf("-1\n");
    else
        printf("%d\n%d\n", sum, Prime_min);
 
    free(arr);
 
    return 0;
}
 
void Seive_of_Eratosthenes(int* arr, int N) {
    int i, j;
 
    for (i = 0; i <= N; ++i) {
        arr[i] = i;
    }
    arr[1= 0;
 
    for (i = 2; i*<= N; ++i) {
        if (arr[i] == 0)
            continue;
        for (j = i * 2; j <= N; j += i) {
            arr[j] = 0;
        }
    }
}
cs

 

반응형
코드설명

 

1
#pragma warning(disable:4996)
cs

Visual Studio에서 scanf 함수를 실행했을 때 발생하는 경고 메시지를 무시하기 위한 코드입니다.

 

 

1
2
#include <stdio.h>
#include <stdlib.h>
cs

stdio.h와 stdlib.h 헤더 파일을 포함합니다. stdio.h는 입력과 출력을 위한 함수들을 제공하고, stdlib.h는 메모리 동적 할당과 관련된 함수들을 제공합니다.

 

 

1
void Seive_of_Eratosthenes(int *arr, int N);
cs

Seive_of_Eratosthenes 함수를 선언합니다. 이 함수는 배열과 배열의 크기를 인자로 받아서 소수를 찾습니다.

 

 

1
int M, N, i, *arr = NULL, sum = 0, flag = 0, Prime_min;
cs

int형 변수 M, N, i, sum, flag, Prime_min을 선언합니다. arr은 포인터로 선언하고, NULL로 초기화합니다.

 

 

1
scanf("%d %d"&M, &N);
cs

사용자로부터 M과 N을 입력받습니다.

 

1
2
3
arr = (int*)malloc((N+1* sizeof(int));
if (arr == NULL)
    return -1;
cs

N+1만큼의 크기를 갖는 int형 배열 arr을 동적으로 할당합니다. 메모리 할당에 실패하면 -1을 반환하고 종료합니다.

 

1
Seive_of_Eratosthenes(arr, N);
cs

Seive_of_Eratosthenes 함수를 호출하여 배열 arr에서 소수를 찾습니다.

 

1
2
3
4
5
6
7
8
9
10
11
for (i = M; i <= N; ++i) {
    if (arr[i] != 0) {
        //소수 중 최솟값
        if (flag == 0) {
            Prime_min = arr[i];
            flag = 1;
        }
        sum += arr[i];
    }
}
 
cs

M부터 N까지의 숫자 중에서 소수를 찾아서 합과 최솟값을 구합니다.

 

 

1
2
3
4
if (sum == 0)
    printf("-1\n");
else
    printf("%d\n%d\n", sum, Prime_min);
cs

sum이 0이면 -1을 출력하고, 그렇지 않으면 sum과 Prime_min을 출력합니다.

 

 

1
free(arr);
cs

arr 배열에 할당된 메모리를 해제합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Seive_of_Eratosthenes(int* arr, int N) {
    int i, j;
 
    for (i = 0; i <= N; ++i) {
        arr[i] = i;
    }
    arr[1= 0;
 
    for (i = 2; i*<= N; ++i) {
        if (arr[i] == 0)
            continue;
        for (j = i * 2; j <= N; j += i) {
            arr[j] = 0;
        }
    }
}
cs

Seive_of_Eratosthenes 함수입니다. 에라토스테네스의 체 알고리즘을 이용하여 arr 배열에서 소수를 찾습니다.

먼저 arr 배열을 0부터 N까지 초기화합니다. 그리고 arr[1]을 0으로 설정합니다. 1은 소수가 아니므로, 소수가 아님을 표시하기 위해서 0으로 설정합니다.

i가 2부터 sqrt(N)까지 반복하는 동안, arr[i]가 0이 아니면(즉, 소수라면), i의 배수들을 0으로 설정합니다. 그리고 i를 증가시켜 다음 소수를 찾습니다.

예를 들어, i가 2일 때, arr[2]가 소수이므로, arr[4], arr[6], arr[8], ...을 0으로 설정합니다. 그리고 i를 3으로 증가시켜 다음 소수를 찾습니다.

이렇게 arr 배열을 모두 탐색하면, arr 배열에는 소수들이 0이 아닌 값으로 남게 됩니다.

 

 

느낀점

 

- 예전에 사용해보았던 에라토스테네스의 체 알고리즘을 다시 사용해보면서 복습할 수 있어서 좋았다.

- chatGPT가 내가 작성한 코드를 이렇게 잘 설명할 수 있을 줄은 몰랐는데 내가 작성한 의도에 맞게 설명하는 것을 보고 조금 놀랐따.

- 동적할당을 굳이 사용하지는 않아도 되지만, 사용해서 나쁠건 없다.

728x90
반응형