zoukankan      html  css  js  c++  java
  • 洛谷 P1582 倒水

    题目描述

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

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

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

    输入输出格式

    输入格式:

     

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

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1:
    3 1
    
    输出样例#1:
    1
    
    输入样例#2:
    13 2
    输出样例#2:
    3
    输入样例#3:
    1000000 5
    输出样例#3:
    15808
    思路:依题意可得,每2^x个瓶子可以合成一个瓶子。以样例13 5来说,13=8+4+1.也就是说13个瓶子可以合并成3个瓶子,但此时不满足“小于k个”条件,所以需要购买空瓶子。买1个,14=8+4+2,没有什么卵用。买2个,15=8+4+2+1,好像更糟。买3个,16=16,搞定。根据上述过程可以得出初步思路:算出n可以分成几个2^x相加,也就是可以合成几个瓶子。如果结果>k那么买一个空瓶重复上述过程。但是这里需要一个小技巧,如果你分解数的时候暴力枚举,时间肯定爆炸。由于是2^x,所以我们很容易地想到2进制。所有2的倍数的二进制都是100000……(好多好多的0)观察样例13的二进制: 1101.相当于二进制1000+100+1即十进制8+4+1.得出结论,要统计有多少个因子(好像不叫因子,反正就那意思),只需要数数当前瓶子数的2进制下有多少个1即可。那么我们需要一位位比较。如果把整个数转成二进制时间不说了。如何快速的获得此数二进制数下的某一位呢?我们只需要构造一个数,这个的二进制数是0000000000000000000100000000(1<<N)然后再把当前数与该数按位与,就可以得出当前数二进制下某一位。(啥?你不知道啥叫按位与?)交上去发现悲伤的超时了一个点。所以我们需要优化。其实每一次加1的目的就是为了让数中的0变少。就是需要进位。此时我们把瓶子数量的二进制取反再加一,进位就变得容易多了(好像只快一点点)稍有常识的人都会知道,n的二进制取反再加一就是-n。好了看代码吧。
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,k,ans;
    int main(){
        scanf("%d%d",&n,&k);
        int num=n,deep=0;
        while(num>k){
            deep++;
            if(num%2==0)    num/=2;
            else{
                num=num/2+1;
                ans+=pow(2,deep-1);
            } 
        }
        cout<<ans;
    }
    样例没过的50玄学分
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long n,k,ans;
    int main(){
        scanf("%lld%lld",&n,&k);
        while(1){
            long long num=0;
            for(int i=0;i<=64;i++)
                if((n&((long long)1<<i))>0)    num++;
            if(num<=k)    break;
            ans+=n&(-n);
            n+=n&(-n); 
        }
        cout<<ans;
    }

     

    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    初赛第四场B
    初赛第四场A
    初赛第六场C
    CF 365(2) C 思维,图形模拟 D 树状数组,离线处理,思维
    CF 725C 模拟 725D
    CF 378(2) C D 模拟
    CF 729D 模拟,思维
    CF 729C 模拟,二分
    CF 381(2) D. dfs序,二分,数组模拟维护
    CF 395(2) D.矩形上色,模拟
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7695687.html
Copyright © 2011-2022 走看看