|
| 1 | +```java |
| 2 | +import java.util.*; |
| 3 | +import java.io.*; |
| 4 | + |
| 5 | +public class Main{ |
| 6 | + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); |
| 7 | + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); |
| 8 | + static StringTokenizer st; |
| 9 | + public static void main(String[] args) throws Exception{ |
| 10 | + st = new StringTokenizer(br.readLine()); |
| 11 | + long A = Long.parseLong(st.nextToken()); |
| 12 | + long B = Long.parseLong(st.nextToken()); |
| 13 | + long total = countOnes(B) - countOnes(A-1); |
| 14 | + bw.write(String.valueOf(total)); |
| 15 | + bw.close(); |
| 16 | + } |
| 17 | + public static long countOnes(long N) { |
| 18 | + long result = 0; |
| 19 | + |
| 20 | + // 첫번째 비트: 0,1,0,1,0,1,0,1 -> 주기 2 |
| 21 | + // 두번째 비트: 0,0,1,1,0,0,1,1 -> 주기 4 |
| 22 | + // 세번째 비트: 0,0,0,0,1,1,1,1 -> 주기 8 |
| 23 | + // ... |
| 24 | + for (int i = 0; i < 60; i++) { |
| 25 | + long bitPosition = 1L << i; // 한 주기에 있는 1의 개수 |
| 26 | + |
| 27 | + long cycle = 2L * bitPosition; // 주기 구하기, 규칙을 보면 주기의 앞쪽 반절은 0, 뒤쪽 반절은 1임. |
| 28 | + |
| 29 | + long cycles = (N + 1) / cycle; //0부터 N까지 cycle 개수, 0부터니까 N+1로 구하기 |
| 30 | + |
| 31 | + result += cycles * bitPosition; // 주기 x 한 주기에 있는 1의 개수 = 총 1의 개수 |
| 32 | + |
| 33 | + long remainder = (N + 1) % cycle; // 나머지 구하기 |
| 34 | + if (remainder > bitPosition) { // 나머지가 주기의 반절보다 크면 넘어선 만큼 더 더해줌. |
| 35 | + result += remainder - bitPosition; |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + return result; |
| 40 | + } |
| 41 | +} |
| 42 | +``` |
0 commit comments