洛谷P1582 倒水

题目描述 :

一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。
接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择
两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶
丢弃。(不能丢弃有水的瓶子)
显然在某些情况下CC无法达到目标,比如N=3,K=1。此时CC会重新买一些新
的瓶子(新瓶子容量无限,开始时有1升水),以到达目标。
现在CC想知道,最少需要买多少新瓶子才能达到目标呢?

输入格式 :

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

输出格式 :

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

输入 #1

   3 1

输出 #1

   1

输入 #2

   13 2 

输出 #2

   3

输入 #3

   1000000 5 

输出 #3

15808
1
1
2
1
1
2
4
N二进制合成后二进制K
31141001
13110116100002

通过表格可以发现k等于几,合成后的二进制1的个数一定<=k;

lowbit:

 lowbit(x)计算的结果是2^k,其中k为x在二进制表示下末尾0的的个数

11
+001
=100
//ans=001=1;
13
1101
+0001
=1110
//ans+=0001=1;
+0010
=10000
//ans+=0010=3;
附上代码:

  #include<cstdio>
using namespace std;
/*unsigned popcnt (unsigned u)//自己写记录32 位无符号整数有多少个位为1
{
    unsigned ret = 0;
    while (u)
        {
        u = (u & (u - 1));    
        ret ++;
        }
    return ret;
}*/
int main()
{
 int n,k,ans;
 scanf("%d %d",&n,&k);
 while(__builtin_popcount(n)>k) 
 //__builtin_popcount()用于计算一个 32 位无符号整数有多少个位为1
 //while(pocut(n)>k)
 {
  ans+=n&(-n);//lowbit(x)=x&(-x)
  n+=n&(-n);
 }
 printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值