[C Python] 백준 1929번 소수 구하기
에라토스테네스의 체나 단순 반복문을 활용하여 소수를 구해보자.
Problem
M이상 N이하의 소수를 모두 출력하는 프로그램을 작성하시오.
- 입력
- 첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.
- 출력
- 한 줄에 하나씩, 증가하는 순서대로 소수를 출력한다.
Solve
1. 내 풀이 (에라토스테네스의 체)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#define mil 1000000
int main(void) {
int m, n;
scanf("%d %d", &m, &n);
int arr[mil + 1] = {0, };
arr[1] = 1;
for (int i = 2; i <= mil; i++) {
if (arr[i]) continue;
for (int j = i * 2; j <= n; j += i) arr[j] = 1;
}
for (int i = m; i <= n; i++)
if (arr[i] == 0)
printf("%d\n", i);
return 0;
}
나는 에라토스테네스의 체를 m
부터 n
까지의 수에 대해서 적용하여 소수를 구하였다.
나누어지는 수의 init-expr를 i
, iterator를 j += i
로 설정하여 재간을 부려봤다.
2. 반복문
사후적 풀이 필자는 이 풀이를 생각하지 못했다.
만약 범위에 1이 있다면 1은 소수가 아니기에 iterate 한다.
i
가 j
에 의해 나누어 떨어지는 지 조사하기 위해 j
를 $2$부터 $\sqrt{i}$까지1 iterate 한다.
i
가 j
에 의해 나누어 떨어질 경우 i
는 소수가 아니기에 조사를 중단하고 다음 i
를 조사한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <math.h>
int main(void) {
int m, n;
scanf("%d %d", &m, &n);
for (int i = m; i <= n; i++) {
int isPrime = 1;
int root = (int)sqrt(i);
if (i == 1) continue;
for (int j = 2; j <= root; j++) {
if (i % j == 0) {
isPrime--;
break;
}
}
if (isPrime) printf("%d\n", i);
}
return 0;
}
반복문을 사용할 수 있다는 점은 생각하였지만, 제곱근까지만 iterate 하여 시간복잡도를 줄이는 방법은 생각하지 못했다.
Python으로 위를 구현하면 다음과 같다.
1
2
3
4
5
6
m, n = map(int, input().split())
for i in range(m, n + 1):
if i == 1: continue
for j in range(2, int(i ** 0.5) + 1):
if i % j == 0: break
else: print(i)
Reference
$\sqrt{i}$까지만 iterate 하는 이유는 $i$가 $j$에 의해 나누어 떨어지는 경우, $i$는 $j$의 배수이기에 $j$는 $\sqrt{i}$보다 작거나 같기 때문이다.
가령 $16$이 약수인지 조사하기 위해 우리는 $4$까지만 조사하면 된다. ↩︎
이 게시물은 저작권자의 CC BY 4.0 라이센스를 따릅니다.