[백준] 2581번 : 소수

업데이트:

문제

자연수 M과 N이 주어질 때 M이상 N이하의 자연수 중 소수인 것을 모두 골라 이들 소수의 합과 최솟값을 찾는 프로그램을 작성하시오.

예를 들어 M=60, N=100인 경우 60이상 100이하의 자연수 중 소수는 61, 67, 71, 73, 79, 83, 89, 97 총 8개가 있으므로, 이들 소수의 합은 620이고, 최솟값은 61이 된다







입력

입력의 첫째 줄에 M이, 둘째 줄에 N이 주어진다.

M과 N은 10,000이하의 자연수이며, M은 N보다 작거나 같다.







출력

이상 N이하의 자연수 중 소수인 것을 모두 찾아 첫째 줄에 그 합을, 둘째 줄에 그 중 최솟값을 출력한다.

단, M이상 N이하의 자연수 중 소수가 없을 경우는 첫째 줄에 -1을 출력한다.







예제 입력 1

60
100

예제 출력 1

620
61







예제 입력 2

64 65

예제 출력 2

-1







알고리즘 [ 접근방법 ]

M이상 N이하의 자연수 중 소수인 것을 모두 골라 소수의 합과 최솟값을 찾는 문제이다. 소수인지 아닌지 판별하는 것최소값을 저장하는것 두가지 정도가 핵심이라고 볼 수 있다.





소수판별법① : 일일히 비교하기 소수는 1과 자기자신만을 약수로 가지는 수이므로 for문을 이용해 2부터 자기자신의 수 이전까지 비교하는 방법이 있다. 일반적으로 크기가 작은 수가 소수인지 아닌지 판별할 때 사용하면 좋다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
	
	int test = 0;
	int num = 0;
	int count = 0;

	scanf("%d",&test);
	count = test;	// 입력된 모든 수가 소수라고 설정하고 소수가 아닌경우 하나씩 빼주기 위함
	
	for (int i = 0; i < test; i++) {
		scanf("%d", &num);
		for (int i = 2; i < num; i++) {
			// 소수가 아닌경우
			if (num % i == 0) {
				count--;
				break;
			}
		}
		// 1은 소수가 아니므로 예외처리
		if (num == 1) {
			count--;
		}
	}
	printf("%d", count);

	return 0;
}

위의 코드를 이용해 소수판별을 할 경우 효율이 굉장히 떨어질 수 있다. num이 굉장히 큰 수, 예를들면 10,000,000이라고 하면 for문을 99,999,98번 돌아야 하므로 굉장히 오랜 처리 시간이 필요하다. 처리 시간을 단축시키기 위해 소수를 판별하는 또다른 방법이 있는데 바로 제곱근을 활용하는 것이다.







소수판별법② : 제곱근 활용하기

N의 약수는 무조건 sqrt(N)의 범위에 존재한다.

18을 예시로 들어보면, 18의 약수는 1, 2, 3, 6, 9, 18이고, 18은 1 x 18 / 2 x 9 / 3 x 6 / √18 x √18 / 6 x 3 / 9 x 2 / 18 x 1 처럼 √18을 중심으로 대칭구조를 가진다. 따라서 소수를 판별할때 ①처럼 처음부터 끝까지 비교할 것이 아니라 주어진 수의 제곱근 까지만 비교를 해주면 소요시간을 훨씬 줄일 수 있다!







풀이

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

int main() {

	int m = 0, n = 0;
	double num = 0.0;
	int count = 0, sum = 0;
	int min = 10001;

	scanf("%d", &m);
	scanf("%d", &n);


	for (int i = m; i <= n; i++) {
		num = sqrt(i);
		for (int j = 2; j <= num; j++) {
			// 소수가아닌경우
			if (i % j == 0) {
				count++;
				break;
			}
		}
		// 소수인경우
		if (count == 0 && i!=1) {
			sum += i;
			if (i < min && i!=1) min = i;
		}
		count = 0;
	}


	// 소수가 없는경우
	if (sum == 0) printf("-1");
	else {
		printf("%d\n", sum);
		printf("%d\n", min);
	}

	return 0;
}

댓글남기기