※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1407번 문제인 2로 몇 번 나누어질까 이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/1407
1407번: 2로 몇 번 나누어질까
자연수 N이 주어지면, 자연수를 유지하면서 N을 2로 몇 번까지 나눌 수 있는지를 생각해 볼 수 있다. 즉, N의 모든 약수 중 2의 거듭제곱 꼴이면서 가장 큰 약수를 생각하는 것이다. 예를 들어 15의
www.acmicpc.net
A 이상 B 이하의 수 중 (2의 k거듭제곱)의 배수가 몇 개인지 세는 것은 어렵지 않다.
먼저 모든 수는 2의 0 거듭제곱의 배수이니 A 이상 B 이하의 각 수 k마다 f(k)의 값이 최소 1 이상일 것임을 알 수 있다. 각 k마다 1씩 값을 답에 더해주자.
또한, 2의 1 거듭제곱의 배수인 k에 대해서는 f(k)의 값이 최소 2 이상일 것일 것임을 알 수 있다. 앞선 단계에서 f(k)값의 일부인 1씩은 이미 더했으므로, 2의 1 거듭제곱의 배수인 k 개수만큼 1씩만을 답에 더해주자.
마찬가지로, 2의 2 거듭제곱의 배수인 k에 대해서는 f(k)의 값이 최소 4 이상일 것일 것임을 알 수 있다. 앞선 단계에서 f(k)값의 일부인 2씩은 이미 더했으므로, 2의 1 거듭제곱의 배수인 k 개수만큼 2씩만을 답에 더해주자.
위의 과정을 반복하는 것으로 이 문제는 해결할 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
using namespace std;
typedef long long ll;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
ll L, R; cin >> L >> R; L--;
ll ans = R - L;
ll exp = 1LL << 60;
while (exp > 1) {
ll lcnt = L / exp, rcnt = R / exp;
ans += (rcnt - lcnt) * (exp >> 1);
exp >>= 1;
}
cout << ans;
}
'BOJ' 카테고리의 다른 글
[BOJ 7490 // C++] 0 만들기 (0) | 2022.01.23 |
---|---|
[BOJ 23893 // C++] 알프스의 힘 (0) | 2022.01.22 |
[BOJ 17509 // C++] And the Winner Is... Ourselves! (0) | 2022.01.20 |
[BOJ 17370 // C++] 육각형 우리 속의 개미 (0) | 2022.01.19 |
[BOJ 23890 // C++] 달팽이팽이 (0) | 2022.01.18 |