杯子 (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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM