洛谷 P1582 倒水 解题报告

P1582 倒水

题目描述

一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃。(不能丢弃有水的瓶子)

显然在某些情况下CC无法达到目标,比如N=3,K=1。此时CC会重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以到达目标。

现在CC想知道,最少需要买多少新瓶子才能达到目标呢?

输入输出格式

输入格式:

一行两个正整数,\(N,K(1≤N≤2×10^9,K≤1000)\)

输出格式:

一个非负整数,表示最少需要买多少新瓶子。


题目还是做少了,这几天研究了下数论就想着切题目了。

很明显,这题和二进制有关系。

\(n\)个瓶子,分成若干个\(2^k\)显然才会合法。

如何保证最优呢?发现\(n\)的二进制表示下1的个数即是最优个数,如果最优个数比\(k\)要多,我们考虑加一些瓶子。

取出\(n\)的最低位1和它右边所代表的数字,把这个数字加上去,即可以消去至少一个1。这是一种贪心的思想。

对于求1的个数和取最低位1,我们使用\(lowbit()\)运算,即\(x&-x\)


code:

#include <cstdio>
int n,k,ans=0;
int get(int x)
{
    int sum=0;
    for(;x;x-=x&-x) sum++;
    return sum;
}
int main()
{
    scanf("%d%d",&n,&k);
    while(get(n)>k)
    {
        ans+=n&-n;
        n+=n&-n;
    }
    printf("%d\n",ans);
    return 0;
}


2018.5.29

posted @ 2018-05-30 23:48  露迭月  阅读(222)  评论(0编辑  收藏  举报