p1582 倒水,
傳送門
題目描述
一天,cc買了n個容量可以認為是無限大的瓶子,開始時每個瓶子裡有1公升水。接著~~cc發現瓶子實在太多了,於是他決定保留不超過k個瓶子。每次他選擇兩個當前含水量相同的瓶子,把乙個瓶子的水全部倒進另乙個裡,然後把空瓶丟棄。(不能丟棄有水的瓶子)
顯然在某些情況下cc無法達到目標,比如n=3,k=1。此時cc會重新買一些新的瓶子(新瓶子容量無限,開始時有1公升水),以到達目標。
現在cc想知道,最少需要買多少新瓶子才能達到目標呢?
輸入輸出格式
輸入格式:
一行兩個正整數, n,k( 1\le n\le 2\times 10^9,k\le 10001≤n≤2×10
9,k≤1000 )。
輸出格式:
乙個非負整數,表示最少需要買多少新瓶子。
輸入輸出樣例
輸入樣例#1:
3 1
輸出樣例#1:
1
輸入樣例#2:
13 2
輸出樣例#2:
3
輸入樣例#3:
1000000 5
輸出樣例#3:
15808
這道題目不得不說是非常巧妙的,不了解二進位制的人大概會寫的很複雜而且還不一定寫的出來,而使用二進位制,就變得十分簡單了。不得不說二進位制是非常神奇的東西
分析題意,是要求至少需要多少個1公升的瓶子才能兩兩合起來最後瓶子數不超過k。如果暴力求解的話,恐怕列舉方式很複雜。
但是我們可以想象,對於一直數量的瓶子,比如13,它的二進位制數是8+4+1,即1101
,那麼它加乙個瓶子就是1110
,至少瓶子數不會增多,那麼對於現在的14,1110
,需要加幾個瓶子,會使得合起來之後的瓶子數會減少或不增多呢?很容易知道是2,合起來就是10000
,如果只加乙個,那就變成1111
了,還多了乙個。我們可以觀察發現,它的瓶子數要變少,就需要至少加從右邊數直到第乙個1停止的那個數的數量。而學習過樹狀陣列的同學(或者其他lowbit()函式相關演算法),應該就明白了。
沒錯,上面一段的關鍵,就是引出lowbit函式。n & -n
.
對乙個數的二進位制表示上,有幾位是1,就代表了有幾個瓶子。所以我們可以while迴圈,直到該數的1的位數<=k,不然就一直加n & -n, 調整它的位數, 直到滿足退出迴圈的條件。
所以**也是非常非常簡潔的。
#include
using
namespace
std;
int getone(long
long n)
return cnt;
}int main()
P1582 倒水(二進位制)
p1582 倒水 評測方式 雲端評測 標籤難度 普及 提高 時空限制 1000ms 128mb 最新討論 推薦的相關題目 題目描述 一天,cc買了n個容量可以認為是無限大的瓶子,開始時每個瓶子裡有1公升水。接著 cc發現瓶子實在太多了,於是他決定保留不超過k個瓶子。每次他選擇兩個當前含水量相同的瓶子...
P1582 倒水 二進位制
一天,cc買了n個容量可以認為是無限大的瓶子,開始時每個瓶子裡有1公升水。接著 cc發現瓶子實在太多了,於是他決定保留不超過k個瓶子。每次他選擇兩個當前含水量相同的瓶子,把乙個瓶子的水全部倒進另乙個裡,然後把空瓶丟棄。不能丟棄有水的瓶子 顯然在某些情況下cc無法達到目標,比如n 3,k 1。此時cc...
二進位制 二進位制起源
現代通訊技術的基礎是二進位制編碼。早在1865年麥克斯韋總結出麥克斯韋方程組之前,美國人摩斯 morse 於1837年發明了摩斯電碼和有線電報。有線電報的出現,具有劃時代的意義 它讓人類獲得了一種全新的資訊傳遞方式,這種方式 看不見 摸不著 聽不到 完全不同於以往的信件 旗語 號角 烽火,這也是二進...