zoukankan      html  css  js  c++  java
  • 【t088】倒水

    Time Limit: 1 second
    Memory Limit: 128 MB

    【问题描述】

    一天辰辰买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着辰辰发现瓶子实在太多了,于是他决定保留不超
    过K个瓶子,每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃(不能丢弃有水的瓶
    子)。 显然在某些情况下辰辰无法达到目标,比如N=3,K=1。此时辰辰会重新购买一些新的瓶子(新瓶子容量无限,开始时有1升水)
    以达到目标。
    现在辰辰想知道最少需要多少新瓶子才能达到目标呢?
    【数据规模】
    对于50%的数据,n<=10^7;对于100%的数据如题目。
    【提示】考虑lowbit运算
    【输入格式】

    输入文件一行两个正整数N和K,其中1<=n<=10^9,k<=1000。

    【输出格式】

    输出文件包含一个非负整数,表示最少需要购买的瓶子数量。

    Sample Input

    3 1
    Sample Output

    1

    Sample Input2

    13 2
    Sample Output2

    3

    Sample Input2

    1000000 5
    Sample Output2

    15808

    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=t088

    【题解】

    首先把n转换成二进制;
    这个n能够分成的最小的水的数量就为二进制中1的个数;
    因为2^x的水能够合成1瓶水;
    然后考虑这样的形式
    1 0 1 1 1 0
    如果想让1的个数变少一点;
    可以考虑加上最低位的1对应的数字这里即2
    然后就会变成
    1 1 0 0 0 0
    这样做最少能保证消掉一个0、加上1个0,而且可能会有上面的消除多个0的情况,所以肯定不会变差(1的个数肯定不会变多);
    一直重复上述过程直到1的个数小于等于k就好
    (如果写过树状数组就知道lowbit操作了x&(-x)就是获取最低的1对应的数字)

    【完整代码】

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int MAXN = 100;
    
    int n,k;
    int cnt = 0,ans = 0;
    
    int get_num(int n)
    {
        cnt = 0;
        while (n)
        {
            cnt+=(n&1);
            n>>=1;
        }
        return cnt;
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        rei(n);rei(k);
        while (get_num(n)>k)
        {
            ans+=(n&(-n));
            n=n+(n&(-n));
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    解决VS在查找预编译头使用时跳过
    Very Sleepy使用图文教程
    将Excel数据导入到ArcGIS属性表
    2016工作计划
    免费GIS数据下载网站推荐
    WIN7 (64 位)安装AutoCAD2012失败解决方法
    .resources文件转.resx 文件
    同一Session中的aspx页面的并发限制
    Diving Into Lync Client Logins
    Passing JavaScript Objects to Managed Code
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626645.html
Copyright © 2011-2022 走看看