문제
https://www.acmicpc.net/problem/1407
풀이(20분)
import java.io.*;
import java.util.*;
public class Main {
// 5 9면 일단 5 6 7 8 9 인데 앞 뒤 홀수 2개 빠짐, 6과 8로 생각
// 6 ~ 8 -> 2x ( 1 + 함수(4,4)) 이 4는 나누면서 체크?
// 25 26 27 28 이면 2개 빼고 26 28임
// 13 14면 2 x (1 + 함수(14,14)) 이 함수가 2를 반환할거임
// 176 177 이면 1개 뺴고
// 함수(176, 176)임
// 즉 함수는 시작과 끝이 같다면 그걸 2로 나눌 수 있는 만큼 나누고
// 시작과 끝이 다르면 일단 본인 포함 사이에 있는 홀수 개수 + 함수(제일 첫 짝수, 제일 끝 짝수)의 재귀 구조
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
long A = Long.parseLong(st.nextToken());
long B = Long.parseLong(st.nextToken());
long answer = find(A, B);
System.out.println(answer);
}
static long find(long start, long end){ // 홀수는 빼고, 짝수에 대해서만 추적
if(start == end){ // 시작과 끝이 같다면
int count = 0;
while(true){
if(end % 2 == 1){ // 2로 나눌 수 있는 만큼 나누어 반환
return (long)Math.pow(2, count);
}
end /= 2;
count += 1;
}
}
long oddCounts = 0; // start ~ end 사이에 있는 홀수의 개수
if(start % 2 == 1){ // 시작이 홀수라면 한칸 미루기
start += 1;
oddCounts += 1;
}
if(end % 2 == 1){ // 끝이 홀수라면 한칸 땡기기
end -= 1;
oddCounts += 1;
}
oddCounts += (end - start + 1) / 2; // 사이에 있는 모든 홀수 빼기
// 홀수 개수 + 2 * find(start/2, end/2)의 재귀
// start와 end는 짝수이기 때문에 /2로 재귀
return oddCounts + 2 * find(start / 2, end / 2);
}
}
문제 풀이 전략
문제 자체에서 값의 최대 범위가 10^15이다.
→ 절대 일반적인 구조로 해결할 수 없다.
그렇기에 재귀를 생각했다.
1. 5 9 입력에 대하여 살펴보자.
- 2로 나눈다는 것은 홀수는 무조건 1의 값을 갖게 된다는 뜻이다.
- 그럼 짝수만 생각하면 된다.
- 6, 8을 구한다고 해보자.
- 그럼 f(6) = 2, f(8) = 8이다.
- 2로 나눌 수 있기에, 2로 나눈 3과 4를 기준으로 다시 생각해 보자.
- f(3) = 1, f(4) = 4이다.
- 즉 f(6) + f(8) = 2 * (f(3) + f(4))이다.
- 2로 나눌 수 있는 4를 다시 생각해 보자.
- 4는 제곱수이기 때문에 별다른 값이 아닌 바로 반환한다.
2. 176 177을 봐보자.
- 176 177 사이에 홀수는 모두 뺄 것이기 때문에 176만 남는다.
- function(176,176)이다.
- 시작과 끝이 같으므로 이 수가 2로 몇 번 나눌 수 있는지만 파악한다.
- 리턴한다.
3. 25 28을 살펴보자.
- 25 28 사이에 홀수를 모두 빼고 시작과 끝을 잡자.
- 25, 27 이 빠지고 시작과 끝은 26, 28로 맞춰진다.
- 2 + 2*find(13,14)가 된다. (2를 곱하는 이유는 2로 나누어 전달할 것이기 때문이다.)
- 13,14의 경우 13이 홀수이기 때문에 시작 : 14, 끝 : 14로 되어 1 + 2 * find(7,7)이 된다.
- find(7,7)은 시작과 끝이 같기 때문에 2로 나눌 수 있는 만큼 나누고 1로 반환된다.
'문제 풀이 > 백준' 카테고리의 다른 글
[백준] 1774번. 우주신과의 교감(JAVA) (0) | 2025.04.07 |
---|---|
[백준] 1744번. 수 묶기(JAVA) (0) | 2025.04.05 |
[백준] 1322번. X와 K(JAVA) (0) | 2025.04.04 |
[백준] 3980번. 선발 명단(JAVA) (0) | 2025.04.04 |
[백준] 2610번. 회의준비(JAVA) (1) | 2025.04.02 |