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