1. 程式人生 > >[HNOI2006]鬼谷子的錢袋

[HNOI2006]鬼谷子的錢袋

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]鬼谷子的錢袋