은 비트 정수 자료형 long보다는 작습니다. 따라서 에 있을 수 있는 최대 켜져있는 비트는 비트보다는 작다고 생각할 수 있습니다. bitCount()의 값을 라고 하겠습니다.
인 경우는 어떨까요? 아무리 적어도 한 번에 한 개의 비트는 변환해야하니까 정확히 번만에 으로 변환하는 것은 불가능합니다. 반면에 인 경우는 언제나 변환할 수 있음을 알 수 있습니다.
는 변환 과정에서 생기는 차들의 집합입니다. 최댓값 - 최솟값을 최소화하고자 한다면 당연히 최댓값은 작게, 최솟값은 크게 만들도록 노력해야겠죠.. 그런데 최댓값은 아무리 작게 만들어봐야 가장 큰 비트를 변환할 때 보다 작게 만들수는 없습니다. 최솟값을 크게 만드는 것이 관건입니다.
에서 아무 비트나 개씩 줄여가면 로 만들 수 있습니다. 는 변환 과정에서 생기는 차들의 집합이기 때문에, 변환하는 순서는 상관이 없습니다. 의 최대는 가장 큰 켜진 비트, 최소는 가장 작은 켜진 비트가 되겠죠.
변환은 번 해야하는데 비트 수가 개 더 많습니다. 중간에 한 번에 개를 변환하는 과정이 있어야겠죠. 의 최솟값을 최대화하기 위해서는 최하위 켜진 비트 개를 켜는것이 최적입니다. 이걸 확장시켜서 일반화할 수 있습니다. 라면 의 최솟값을 최대화하기 위해서 최하위 켜진 비트 개를 동시에 꺼줍니다. 이제 남은 비트는 개가 남았고 남은 횟수도 개이므로 아무 비트나 한 개씩 끄면서 됩니다.
public class Main {
static String solve(long B, int N) {
int cnt = Long.bitCount(B);
if (cnt < N) return "-1";
StringBuilder bw = new StringBuilder();
int range = cnt - N + 1;
// 제일 처음에 끝에서 range개의 비트를 제거
for (int i = 0; i < range; i++) B -= (B & -B);
bw.append(B).append(" ");
while (B > 0) {
B -= (B & -B);
bw.append(B).append(" ");
}
return bw.toString();
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder bw = new StringBuilder();
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
long B = Long.parseLong(st.nextToken());
int N = Integer.parseInt(st.nextToken());
bw.append(solve(B, N));
System.out.println(bw);
}
}