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;
    }
  • 相关阅读:
    Candy leetcode java
    Trapping Rain Water leetcode java
    Best Time to Buy and Sell Stock III leetcode java
    Best Time to Buy and Sell Stock II leetcode java
    Best Time to Buy and Sell Stock leetcode java
    Maximum Subarray leetcode java
    Word Break II leetcode java
    Word Break leetcode java
    Anagrams leetcode java
    Clone Graph leetcode java(DFS and BFS 基础)
  • 原文地址:https://www.cnblogs.com/chenjiaxuan/p/10821307.html
Copyright © 2011-2022 走看看