본문 바로가기

자바 자료구조 & 알고리즘/알고리즘 문제 풀이

백준 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보다 작거나 같다.

60
100

출력

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

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

620
61

내 코드

package com.heejin.baekjoon.ex09;

import java.util.Scanner;

public class No2581 {
  
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int sum = 0;
    int sosuMin = 0;
    int min = sc.nextInt();
    int max = sc.nextInt();
    
    boolean[] sosus = sosus(min, max);
    for (int i = 0; i < sosus.length; i++) {
      if (sosus[i] == false) {
        if (sosuMin == 0) {
          sosuMin = i + min;
        }
        sum += i + min;
      }
    }
    
    if (sum == 0) {
      System.out.println(-1);
    } else {
      System.out.println(sum);
      System.out.println(sosuMin);
    }
  }
  
  static boolean[] sosus(int min, int max) {
    boolean[] whole = new boolean[max - min + 1];
    if (min == 1) {
      whole[0] = true;
    }
    for (int i = 2; i <= max; i++) {
      for (int j = 2; j <= max / 2 ; j++) {
        if (i * j > max) {
          break;
        }
        if (i * j >= min) {
          whole[i * j - min] = true; 
        }
      }
    }
    return whole;
  }
}

사실 1978번을 풀 때 구현한 메서드는 2581번을 풀면서 만든 메서드를 그대로 갖고 온것이다. 여기서 저번에 에라토스테네스의 체를 이용해서 만든 sosus(int min, int max)를 그대로 사용할 수 있다. 

 

다만 이번에는 소수 중 최솟값과 합계를 구하고 소수가 하나도 없다면 -1을 출력하면 된다. 소수 중 최솟값은 배열에서 작은 값부터 큰 값까지 순서대로 값을 확인하기 때문에 최초로 만나는 false에 해당하는 인덱스 값을 변수에 저장하고, 이 변수의 값을 끝까지 유지해주면 된다. sosuMin이라는 변수를 0으로 초기화하고, 최초로 false인 항목을 만났을 때 변수값이 0이면 그 인덱스 값을 변수에 저장한다. 그 다음부터는 변수의 값이 0이 아니므로 변수 값을 변경하는 일은 없을 것이다.