메모리: 14260 KB, 시간: 100 ms
비트마스킹, 수학, 누적 합
2025년 1월 22일 17:40:11
두 자연수 A, B가 주어졌을 때, A ≤ x ≤ B를 만족하는 모든 x에 대해 x를 이진수로 표현했을 때 1의 개수의 합을 구하는 프로그램을 작성하시오.
즉, f(x) = x를 이진수로 표현 했을 때 1의 개수라고 정의하고, 아래 식의 결과를 구하자.

첫 줄에 두 자연수 A, B가 주어진다. (1 ≤ A ≤ B ≤ 1016)
1의 개수를 세어 출력한다.
dp[i] = ((long) Math.pow(2, i)) + (dp[i-1] * 2)
/**
* Author: yngbao97, Yuk Yejin
* Problem: 1의 개수 세기_9527
* Date: 2025.01.22
*/
import java.util.*;
import java.lang.*;
import java.io.*;
public class Main {
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
static long[] dp;
public static void main(String[] args) throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
init();
String[] input = br.readLine().split(" ");
long A = Long.parseLong(input[0]);
long B = Long.parseLong(input[1]);
long fx_A = getOne(A - 1);
long fx_B = getOne(B);
bw.write(String.valueOf(fx_B - fx_A));
bw.flush();
bw.close();
br.close();
}
private static void init()
{
dp = new long[56];
dp[0] = 1;
for (int i = 1; i < 56; i++) dp[i] = ((long) Math.pow(2, i)) + (dp[i-1] * 2);
}
private static long getOne(long num) {
long copy = num;
long cnt = 0;
for (int i = 55; i > 0; i--) {
if (((1L << i) & num) > 0) {
copy -= (1L << i);
cnt += dp[i-1] + (copy + 1);
}
}
if ((num & 1) > 0) cnt++;
return cnt;
}
}