[HNOI2006]鬼谷子的錢袋
阿新 • • 發佈:2018-08-19
can 並且 就是 好的 輸入 return names 最大的 cpp 個金幣,你能猜到他會用多少個錢袋,並且每個錢袋裝多少個金幣嗎?
題目描述
鬼谷子非常聰明,正因為這樣,他非常繁忙,經常有各諸侯車的特派員前來向他咨詢時政。有一天,他在鹹陽遊歷的時候,朋友告訴他在鹹陽最大的拍賣行(聚寶商行)將要舉行一場拍賣會,其中有一件寶物引起了他極大的興趣,那就是無字天書。但是,他的行程安排得很滿,他他已經買好了去邯鄲的長途馬車標,不巧的是出發時間是在拍賣會快要結束的時候。於是,他決定事先做好準備,將自己的金幣數好並用一個個的小錢袋裝好,以便在他現有金幣的支付能力下,任何數目的金幣他都能用這些封閉好的小錢的組合來付賬。鬼谷子也是一個非常節儉的人,他想方設法使自己在滿足上述要求的前提下,所用的錢袋數最少,並且不有兩個錢袋裝有相同的大於1的金幣數。假設他有m
輸入格式
包含一個整數,表示鬼谷子現有的總的金幣數目
m
。其中,1≤m ≤1000000000
。
輸出格式(bzoj)
只有一個整數
h
,表示所用錢袋個數
輸出格式
第一行一個整數
h
,表示所用錢袋個數
第二行h
個整數,表示每個錢袋錢數
樣例輸入
3
樣例輸出(bzoj)
2
樣例輸出(luogu)
2
1 2
重點:~無字天書!~ 任何數目的金幣他都能用這些封閉好的小錢的組合來付賬
同多重背包將錢數二進制分解後,bzoj就能通過了
luogu:分解後會出現剩余的錢是二進制分解出的一部分
例:
輸入
9
輸出
4
1 2 2 4
解決也很簡單(emm)將前面的-1,後面的+1
code:
#include<cstdio> #include<algorithm> using namespace std; int main() { int a[10000]; int m,k=1,ans=0; scanf("%d",&m); while(m>=k){ m-=k; a[ans++]=k; k<<=1; } if(m)a[ans++]=m; sort(a,a+ans); printf("%d\n",ans); for(int i=0;i<ans;i++){ if(a[i]==a[i-1]&&a[i]>1){ a[i-1]--; a[i]++; } } for(int i=0;i<ans;i++){ printf("%d ",a[i]); } return 0; }
[HNOI2006]鬼谷子的錢袋