P1582 倒水

二进制题目,第一次正式接触二进制操作。


因为水杯只有水量相等的才能合成,所以一定是\(2^i\)

这种标志可以用二进制表示,每一位刚好就是上面的表达方式。

把题意翻译到二进制数字上就是:二进制上为1的位数数目

那么问题终于来了:如何数出一个二进制数字上1的多少?

这里有两种方法。

  1. 暴力的。我们可以搞一个数字初始化为1,然后每一次就左移1位,那么我们可以对每一位进行检查,复杂度应该是\(O(logn)\)

  2. 稍有优化的。还记得树状数组中的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;
}
posted @ 2018-08-19 00:14  Garen-Wang  阅读(110)  评论(0编辑  收藏  举报