P1582 倒水

题目描述

一天,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










本道题要注意是2的几次方,先通过输入的n,不断减去能减去的最大的2的n次方,且将这个n的位置标为1.

这样的话就能得到一个01串,如果1的个数就是瓶子的个数,如果小于k的数量,就输出0,如果不是,就从左往右找第一个1,设该位置为x的话

你就加上2的x次个瓶子,然后推一下判断这时瓶子个数是否少于k个

#include<bits/stdc++.h>

using namespace std;

int a[40];
int biao[40];

int main()
{
    int n , k;
    cin >> n >> k;
    long long  maxx = 1 ;
    int num = 0;
    while(maxx < 2000000000)
    {
        biao[num] = maxx;
        maxx *= 2;
        num ++;
    }
    int sum = 0 , he = 0;
    for(int i = num - 1 ;i >= 0  ;i  --)
    {
        if(n >= biao[i])
        {
            n -= biao[i];
            a[i] = 1;
            sum ++; 
            //cout << i << " ";
        }
    }
    //cout << endl;
    while(sum > k)
    {
        int i = 0;
        for( i ; i < num  ; i ++)
        {
            if(a[i] == 1)
                break;
        }
        a[i] = 0 ;
        he += biao[i];
        a[i + 1] ++ ;
        for(int j = i + 1; j < num ; j ++)
        {
            if(a[j] == 2)
            {
                a[j + 1] ++;
                a[j] = 0;
                sum --;
            }
            else
                break;
        }
    }
    cout << he;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值