P1582 倒水(二进制)
https://www.luogu.org/problemnew/show/P1582
P1582 倒水
評測方式 云端評測
標簽
難度 普及+/提高
時空限制 1000ms / 128MB
提示:收藏到任務計劃后,可在首頁查看。
最新討論
推薦的相關題目
題目描述
一天,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:
輸出樣例#1:
1輸入樣例#2:
13 2輸出樣例#2:
3輸入樣例#3:
1000000 5輸出樣例#3:
15808ac_code:
/*
這題沒有提高難度,就是普及吧~
實質是二進制的應用吧
/
自己是這樣做的
/
補充一個解釋:
A:瓶子先水量相同的兩兩合并,如果是一開始n為奇數,肯定會剩下一份不能兩兩合并的,如果是偶數,就剛好兩兩合并,不會剩下。如果剩下一份,這一份的水量 肯定是這次能合并的任意一份水量的 1/2。
經過兩兩合并后,瓶子剩下的個數為n/2,除了那個不能合并的(水量不變),每個瓶子中的水量為之前的兩倍,
對剩下的水量相同的繼續兩兩合并,即重復A。。
經過多次A操作后,最后沒有能兩兩相同水量的合并了,即現在剩下的都是每次A操作剩下的不能進行兩兩相同合并的瓶子,如果此時瓶子個數小于等于m則不需要買瓶子,否則,這樣買:
先買第一次A操作與第二次A操作剩下那個瓶子的水量的差值個瓶子,使它又可以兩兩合并,再直到不能兩兩合并,重復這個購買操作,直到剩下的瓶子小于等于m
舉個例子:
n = 7 m = 2
第一次A:7/ 2 = 3 ,7 % 2 = 1(剩下這個不能合并的瓶子水量為1)
第二次A: 3 / 2 = 1 ,3 % 2 = 1(剩下這個不能合并的瓶子水量為 2)
此時不能進行A操作了,剩下3個瓶子,瓶子水量分別為 :4 ,2 ,1
此時我們要先買1個瓶子,這時:4 ,2,1,1
又可以兩兩合并:
4 ,2 ,2
4 ,4(此時已經滿足條件)
8(當然購買這次后可以最終使它剩下1個水量為8的瓶子)
最后可以只剩下1個瓶子,所以買1個瓶子就可以了
(我們最初的目的是要先讓已有的瓶子經過合并后盡可能的少,所以一直重復A操作,直到不能再進行A操作)
*/
way1:
做完之后去看題解
發現還可以寫的更簡單微妙些
(
其實根據我自己寫的那份代碼也可以發現其中的奧秘所在:
n二進制1的個數,為最初可以剩下的最少個數
之后,n += (n & -n)
//相當于使n的二進制最后一個1上加1,產生進位(連續的1變為0),
但是對于十進制,瓶子加的個數肯定是(n & -n),所以ans += (n & -n),
直到n的二進制1個數不超過m
)
way2:
//bitset,lowbit
way3:
//__builtin_popcount lowbit
/*
個人覺得沒有必要知道gcc里的__builtin_…
(如果實在想了解gcc里的__builtin_…點這里吧:gcc里的__builtin_…傳送門)
因為bitset差不多可以完全取得它,而且功能更加強大同時也更好記函數形式更好理解
(用bitset好像效率也更高的樣子,提交是快了兩毫秒)
了解bitset的用法點這里:bitset傳送門
*/
總結
以上是生活随笔為你收集整理的P1582 倒水(二进制)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gcc里的__builtin_..
- 下一篇: myBitSet