Open yeongleej opened 4 days ago
이 방법은 t가 2의제곱꼴일 경우만 사용 가능 (예시 3처럼 K가 2배수 아니면 사용 불가) → 2의제곱 형태를 더 활용하기
비트 활용
Integer.bitCount(N)
: 현재 숫자의 비트에서 1의 수 구하기
O(logN)
int lowPos = N & -N;
: 가장 낮은 자리 비트 구하기
-N
은 N을 보수연산한 것으로 가장 낮은 자리 번호를 제외하고 0과 1뒤바뀜.2^x + 2^y + ...
의 항의 개수가 k개 이하
여야 합쳐서 옮기는 것이 가능1의 비트가 k개 이하
가 되도록 연산Integer.bitCount(n)
: n이 갖는 1의비트 수Integer.lowestOneBit(n)
: n의 마지막 1의 비트의 값
while (Integer.bitCount(n) > k) {
// 최소한의 수를 더하여 비트 줄이기
cnt += Integer.lowestOneBit(n);
n += Integer.lowestOneBit(n);
}
=> O(N)으로 생각해보기
N의 값은 (2^0, 2^1, ....들의 합)이 되어야 함
K >= N이라면 한번에 모든 물병 들 수 있으므로 0
내가 푼 과정
2^i
을 계속 빼줘서 물병 사용하기2^i
는 N보다 작은 최대 2의 제곱수2^i
> N인 값 구하기2^i
- N == N이 2^i
가 되기 위해 구매햐야 하는 물병 수Integer.bitCount(N)
: N(10)을 2진수로 나타낸 후 1의 개수
int ans = 0; while(true) { int bc = Integer.bitCount(N); if(bc <= K) break;
N++;
ans++;
}
> 비트연산 쉽지않네요 ㅜㅜㅠㅠ 😢
N은 10^7
K는 10^3
으로 최대 O(N)
이내로 풀이가능N보다 작은 2의 최대 제곱 수
가 합친 최대 물의 양 으로 1개의 물병을 만들 수가 있음
K-1
개 만큼 반복하면서 물병을 만들고, 물병이 0이 된다면 K개 이내로 물병을 만들 수 있다는 뜻으로 반복문을 탈출한다. (상점에서 물병을 살 필요가 없으므로 -1 출력)
for(int i=0; i<K-1; i++){
int count = 0;
while(Math.pow(2,count) < N){ //N개의 물병을 넘지 않는 최대 제곱
count++;
}
N -= (int) Math.pow(2,count-1); //물병 1개를 만들 수 있는 최대양
if(N == 0) {
break;
}
}
K-1
개 반복 후 N 이 남아있다면 상점에서 물병을 사서 보충하기
Math.pow(2,count) < N
2의 제곱만큼 순회를 통해 N 보다 작은 최대 물의 양의 제곱(count
)을 구한 후,(int) Math.pow(2,count) - N
출력그런데
10 3
를 입력하면0
으로 출력 되던데, 정답으로 넘어가더라구요? 0개는 -1 로 출력해야 하는것 아닌가요..??? (그런데 0일 경우 -1 로 변환해서 출력하게 하면 오답으로 돼요)