zoukankan      html  css  js  c++  java
  • 杯子 (glass)

    题目

      试题1:杯子 (glass)
      源代码:glass.cpp
      输入文件:glass.in
      输出文件:glass.out
      时间限制:1s
      空间限制:256MB

    题目描述

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

    输入说明

    一行两个正整数,N,K(1≤N≤1000000000,K≤1000)。
    输出说明
      一个非负整数,表示最少需要买多少新杯子。

    样例输入1

      3 1

    样例输出1

      1

    样例输入2

      13 2

    样例输出2

      3

    样例输入3

      1000000 5

    样例输出3

      15808

    数据范围

      对于50%的数据,N≤10000000;
      对于100%的数据如题目。

    分析

    由于是第一题,而且数据极大(o(n)也做不了),所以这道题要么是贪心,要么是数论,要么是贪心+数论

    仔细阅读题目,你就会发现每一个杯子(除了刚开始的杯子)里的水量都是由两个相等的水量相加而得。

    所以每一个杯子里的水量都是2x(x为非负整数),进而我们知道2y个水量为1杯子可以变成1个杯子(这一个杯子里的水量为2y

    为了使新添的杯子数量最少,所以我们每次要让y最大(贪心)。

    注意:为了避免数值过大,所以最好用long long

    代码

    #include<iostream>
    using namespace std;
    long long n,k,sum=1;
    int main()
    {
        cin>>n>>k;
        if(k>=n)
        {
            cout<<"0";
            return 0;
        }
        long long t=1;
        while(sum<=n) sum<<=1;//"<<"是位运算,和"*2"一样
        long long a=sum>>1;
        while(t<k)//循环k-1次
        {
            while(a>n) a>>=1;//">>"也是位运算,和"/2"一样
            n-=a;
            t++;
        }
        sum=1;
        while(sum<=n) sum<<=1;//计算需要用几个水量为1杯子才能将剩下的所有杯子变成一个杯子
        cout<<sum-n;
        return 0;
    }
  • 相关阅读:
    Windows中启动和关闭Oracle服务的x.bat批处理文件
    Flex删除文件 SecurityError: fileWriteResource
    Eclipse中的@Override标注报错
    Flex删除文件 SecurityError: fileWriteResource
    commonsfileupload 上传文件乱码问题
    Eclipse中的@Override标注报错
    Windows中启动和关闭Oracle服务的x.bat批处理文件
    csdn论坛最近又有人灌水
    用JavaScript获取URL中的参数值
    用JavaScript获取URL中的参数值
  • 原文地址:https://www.cnblogs.com/chenjiaxuan/p/10821307.html
Copyright © 2011-2022 走看看