BOJ 1009 분산처리
2023-05-25
1 min
어떤 정수 X가 1보다 큰 제곱수로 나누어 떨어지지 않을 때, 그 수를 제곱ㄴㄴ수라고 한다. 제곱수는 정수의 제곱이다.
min과 max가 주어지면, min보다 크거나 같고, max보다 작거나 같은 제곱ㄴㄴ수가 몇 개 있는지 출력한다.
첫째 줄에 두 정수 min과 max가 주어진다.
1 ≤ min ≤ 1,000,000,000,000
min ≤ max ≤ min + 1,000,000
해당 문제를 해결하기 위해 가장 먼저 떠올릴수 있는 아이디어는 min부터 max까지의 수를 하나씩 인수분해 하여 제곱의 배수인지 판별하는 방법이다.
하지만 입력되는 숫자가 매우 크기 때문에 위와 같은 방식의 로직은 시간 초과가 발생한다. 따라서 효율적인 방법을 찾아야 한다.
'에라토스테네스의 체'는 주어진 범위 내의 소수를 찾는 알고리즘으로, 이를 응용하면 해당 문제를 효율적으로 풀어 낼 수 있다. '에라토스테네스의 체'에 관한 자세한 내용은 BOJ 1929 소수 구하기에 자세히 정리해 두었다.
에라토스테네스의 체를 응용한 로직은 다음과 같다.
import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); HashSet<Long> set = new HashSet<>(); // 시작과 끝 입력 String[] str = br.readLine().split(" "); long min = Long.parseLong(str[0]); long max = Long.parseLong(str[1]); // 에라토스테네스의 체 int end = (int)Math.sqrt(max); for(long i = 2; i <= end; i++) { long square = i * i; long start = min / square; // 시작점 계산 if(min % square != 0) start++; // 시작점 보정 // set에 제곱수 넣기 for(long j = start; j * square <= max; j++) { set.add(j * square); } } // 전체 개수에서 제곱의 개수 빼기 System.out.println(max - min + 1 - set.size()); } }
#include <iostream> #include <cmath> #include <set> #define fastio ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr) #define endl '\n' using namespace std; int main() { fastio; set<long> s; // 시작과 끝 입력 long min, max; cin >> min >> max; // 에라토스테네스의 체 int end = (int)sqrt(max); for(long i = 2; i <= end; i++) { long square = i * i; long start = min / square; // 시작점 계산 if(min % square != 0) start++; // 시작점 보정 // set에 제곱수 넣기 for(long j = start; j * square <= max; j++) { s.insert(j * square); } } // 전체 개수에서 제곱의 개수 빼기 cout << (max - min + 1 - s.size()) << endl; return 0; }
import kotlin.math.sqrt fun main(args: Array<String>) = with(System.`in`.bufferedReader()) { var set: MutableSet<Long> = mutableSetOf() // 시작과 끝 입력 var str = readLine().split(" ") var min = str[0].toLong() var max = str[1].toLong() // 에라토스테네스의 체 var end = sqrt(max.toDouble()).toInt() for(i in 2..end) { var square = i * i var start = min / square // 시작점 계산 if(min % square != 0L) start++ // 시작점 보정 // set에 제곱수 넣기 for(j in start..(max / square)) { set.add(j * square) } } // 전체 개수에서 제곱의 개수 빼기 println(max - min + 1 - set.size) }
from sys import stdin import math def main(): s = set() # 시작과 끝 입력 str = stdin.readline().split(" ") min = int(str[0]) max = int(str[1]) # 에라토스테네스의 체 end = int(math.sqrt(max)) for i in range(2, end + 1): square = i * i start = min // square # 시작점 계산 if min % square != 0: start = start + 1 # 시작점 보정 # set에 제곱수 넣기 for j in range(start, (max // square) + 1): s.add(j * square) # 전체 개수에서 제곱의 개수 빼기 print(max - min + 1 - len(s)) if __name__ == "__main__": main()
import Foundation func main() { var set = Set<Int64>() // 시작과 끝 입력 var str = readLine()!.split(separator: " ") var min = Int64(str[0])! var max = Int64(str[1])! // 에라토스테네스의 체 var end = Int(sqrt(Double(max))) for i in 2..<end + 1 { var square = Int64(i) * Int64(i) var start = min / square // 시작점 계산 if(min % square != 0) { // 시작점 보정 start += 1 } // set에 제곱수 넣기 for j in start..<(max / square) + 1 { set.insert(j * square) } } // 전체 개수에서 제곱의 개수 빼기 print(max - min + 1 - Int64(set.count)) } main()