码迷,mamicode.com
首页 > 其他好文 > 详细

P1582 倒水

时间:2018-05-21 23:01:26      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:个数   using   psu   hit   list   +=   class   thml   tom   

题目描述

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

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

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

输入输出格式

输入格式:

一行两个正整数, N,K( 1\le N\le 2\times 10^9,K\le 10001N2×109,K1000 )。 

输出格式: 

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

 

输入输出样例

输入样例#1: 
3 1
输出样例#1: 
1
输入样例#2: 
13 2
输出样例#2: 
3
输入样例#3: 
1000000 5
输出样例#3:
15808

Solution

二进制水题一道.

因为只有当有两个相同的水瓶时才可以合并;

所以可以很快推出一条性质:

每个合并出来的水瓶最终水量必为 2 的 n 次方.

 

然后也就是说,把当前这个数转化成二进制,它共有多少位是 1 , 也就是它可以合并出来的水瓶.

因为只能加,所以我们就一步一步把这个数字跳为恰有 k 个1的最小值即可.

 

关于取一的个数;

树状数组引用过一个 x&(-x) 便能取出末尾的1.

每次取玩减去即可.

 

 

代码

#include<bits/stdc++.h>
using namespace std;
int n,k,ans;
int pal(int x)
{
    int num=0;
    while(x)
    {
        num++;
        x-=x&-x;
    } 
    return num;
}
int main(){
    scanf("%d%d",&n,&k);
    while(pal(n)>k) 
    ans+=n&-n,n+=n&-n;
    cout<<ans<<endl;
    return 0;
}

 

P1582 倒水

标签:个数   using   psu   hit   list   +=   class   thml   tom   

原文地址:https://www.cnblogs.com/Kv-Stalin/p/9069593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!