P1582 倒水
二进制题目,第一次正式接触二进制操作。
因为水杯只有水量相等的才能合成,所以一定是\(2^i\)。
这种标志可以用二进制表示,每一位刚好就是上面的表达方式。
把题意翻译到二进制数字上就是:二进制上为1的位数数目。
那么问题终于来了:如何数出一个二进制数字上1的多少?
这里有两种方法。
-
暴力的。我们可以搞一个数字初始化为1,然后每一次就左移1位,那么我们可以对每一位进行检查,复杂度应该是\(O(logn)\)。
-
稍有优化的。还记得树状数组中的
lowbit
函数吗?能够减掉多少次lowbit其实就是有多少个1。
当新得到数字大于\(k\)时,我们还需要继续枚举。
可以发现如果无脑地加1的话答案不会更优,其实我们可以加一个lowbit
。
然后就能过了。
代码:
#include<cstdio>
int n, k, ans;
int lowbit(int x)
{
return x & -x;
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = 0; ; )
{
int cnt = 0;
for(int j = 0; (1 << j) <= n; j++) if(n & (1 << j)) cnt++;
if(cnt <= k) break;
ans += lowbit(n);
n += lowbit(n);
}
printf("%d\n", ans);
return 0;
}