洛谷P1582 倒水 二進位制

2022-02-27 06:10:21 字數 1539 閱讀 5939

一天,cc買了n個容量可以認為是無限大的瓶子,開始時每個瓶子裡有1公升水。接著~~cc發現瓶子實在太多了,於是他決定保留不超過k個瓶子。每次他選擇兩個當前含水量相同的瓶子,把乙個瓶子的水全部倒進另乙個裡,然後把空瓶丟棄。(不能丟棄有水的瓶子)

顯然在某些情況下cc無法達到目標,比如n=3,k=1。此時cc會重新買一些新的瓶子(新瓶子容量無限,開始時有1公升水),以到達目標。

現在cc想知道,最少需要買多少新瓶子才能達到目標呢?

一行兩個正整數,n,k(1<=n<=2*10^9,k<=1000)。

乙個非負整數,表示最少需要買多少新瓶子。

輸入 #1

3 1輸出 #1

1輸入 #2

13 2

輸出 #2

3輸入 #3

1000000 5

輸出 #3

15808

只有水容量相同的瓶子才可以倒在一起,初始瓶子水為1公升,且瓶子無限大,問你給你 n 個瓶子,還需要幾個瓶子才能使得最後還剩 k個有水的瓶子。

先考慮最後剩乙個瓶子,那麼開始肯定要

個瓶子,最後才可以倒成乙個瓶子。如果開始給你n個瓶子,設還需要x個瓶子可以寫成:  n + x =

,這樣如果最後剩乙個瓶子,那麼可以讓n構成最小的

的x就是答案。那麼最後如果剩 k 個瓶子呢? 可以這樣想:最後剩k個瓶子,但可以把這k個瓶子看成獨立的乙個乙個的瓶子,最後又變成最後剩乙個瓶子的問題了,公式就可以寫成:

n + x =

++ ······ +

,所以最後問題變成如何加上最小的x使得 n + x 可以拆成k個2的次方的形式,每個2的次方最終就會倒水倒成1。設 ans = n + x 其實最後就是讓ans的二進位制的1的個數小於等於 k 就好,因為大於k的話一定無法拆解成 k 個2的次方的形式,肯定多餘k個,若果最後的答案的二進位制的個數小於k個,那麼最後就可以拆了,比如:

n = 13, k = 2 讓你求x

n = 1 1 0 1, 先加0 0 0 1 => 1 1 1 0 ,在加 0 0 1 0  => 1 0 0 0 0  每次加最低位,保證盡可能慢慢擴大x(貪心),這時候就剩1個二進位制位了,可以拆成 :

+的形式。

補充小知識點:

1、__builtin_popcount(n) (前面倆下劃線_)用於求計算n表示成二進位制時有多少個1。(不需要任何標頭檔案就可以使用)

2、n & (-n) 代表每次加上乙個是最後乙個1向前進製的大小,即求lowbit(n)。

1 #include 2

using

namespace

std;34

//k為x的二進位制中從最低位到高位連續零的長度,返回2^k大小

5int lowbit(intx)8

9int

main()

16 cout

17return0;

18 }

參考:

P1582 倒水(二進位制)

p1582 倒水 評測方式 雲端評測 標籤難度 普及 提高 時空限制 1000ms 128mb 最新討論 推薦的相關題目 題目描述 一天,cc買了n個容量可以認為是無限大的瓶子,開始時每個瓶子裡有1公升水。接著 cc發現瓶子實在太多了,於是他決定保留不超過k個瓶子。每次他選擇兩個當前含水量相同的瓶子...

P1582 倒水 二進位制

一天,cc買了n個容量可以認為是無限大的瓶子,開始時每個瓶子裡有1公升水。接著 cc發現瓶子實在太多了,於是他決定保留不超過k個瓶子。每次他選擇兩個當前含水量相同的瓶子,把乙個瓶子的水全部倒進另乙個裡,然後把空瓶丟棄。不能丟棄有水的瓶子 顯然在某些情況下cc無法達到目標,比如n 3,k 1。此時cc...

洛谷P1582 倒水

一天,cc買了n個容量可以認為是無限大的瓶子,開始時每個瓶子裡有1公升水。接著 cc發現瓶子實在太多了,於是他決定保留不超過k個瓶子。每次他選擇兩個當前含水量相同的瓶子,把乙個瓶子的水全部倒進另乙個裡,然後把空瓶丟棄。不能丟棄有水的瓶子 顯然在某些情況下cc無法達到目標,比如n 3,k 1。此時cc...