P2320 [HNOI2006]鬼谷子的錢袋(分治思想,水題)
阿新 • • 發佈:2018-11-09
題目描述
鬼谷子非常聰明,正因為這樣,他非常繁忙,經常有各諸侯車的特派員前來向他諮詢時政。
有一天,他在咸陽遊歷的時候,朋友告訴他在咸陽最大的拍賣行(聚寶商行)將要舉行一場拍賣會,其中有一件寶物引起了他極大的興趣,那就是無字天書。
但是,他的行程安排得很滿,他已經買好了去邯鄲的長途馬車票,不巧的是出發時間是在拍賣會快要結束的時候。於是,他決定事先做好準備,將自己的金幣數好並用一個個的小錢袋裝好,以便在他現有金幣的支付能力下,任何數目的金幣他都能用這些封閉好的小錢的組合來付賬。
鬼谷子也是一個非常節儉的人,他想方設法使自己在滿足上述要求的前提下,所用的錢袋數最少,並且不有兩個錢袋裝有相同的大於1的金幣數。假設他有m個金幣,你能猜到他會用多少個錢袋,並且每個錢袋裝多少個金幣嗎?
輸入輸出格式
輸入格式:
包含一個整數,表示鬼谷子現有的總的金幣數目m。其中,1≤m ≤1000000000。
輸出格式:
兩行,第一行一個整數h,表示所用錢袋個數
第二行表示每個錢袋所裝的金幣個數,由小到大輸出,空格隔開
輸入輸出樣例
輸入樣例#1: 複製
3
輸出樣例#1: 複製
2
1 2
題解:
此題遇到了分治思想,就是把一個大的問題,逐漸轉化為很多小的問題,再去求解。
比如這道題,當我們要求一個數假如為20時,我們要用盡可能少的錢袋來保證我們能
拿出1~20裡面的所有數,我們可以轉化為我們先拿10然後保證能拿1~10裡面的數。因
為1~10+10就可以表示1-20裡面的所有數。同理,下一次就是10+5+1~5,再下一次就是
10+5+3+1~2,最後就是10+5+3+1+1。這樣我們就實現了整個過程。總的來說就是將大
的問題逐漸分解拆分,最後實現我們要的目的。
程式碼:
#include <bits/stdc++.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#define exp 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int a[100005]; //存拆分的數字
int main()
{
int m,sum=0;
cin>>m;
while(m>0)
{
if(m%2==0) a[sum]=m/2;
else a[sum]=m/2+1;
m/=2;sum++; //一步一步拆分,分治
}
sort(a,a+sum); //排序
cout<<sum<<endl;
for(int i=0;i<sum;i++)
cout<<a[i]<<" ";
return 0;
}