[HNOI2006]鬼谷子的钱袋

题面

link

solution

用二进制表示是最少的

把m变成二进制,那么用m的二进制的位数那么多钱袋就可以了

比如m=11010

那么多个钱袋放1,10,100,1000,10000,最多可以达到1111

所以这道题就是求m的二进制位数

实际上本题就是“多重背包的二进制优化”,用二进制拆分就行,然而题中说两数除了1之外都不能相同,比如9,拆分后就是1 2 4 2, 不符合,对拆分序列进行排序,在拆分的时候遇到a[i] == a[i + 1] 的情况,就a[i]--, a[i + 1]++就行,最终得到拆分的方案。

code

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;

int m, cnt, a[maxn];

int main()
{
    cin>>m;
    int x = 1;
    while(m - x > 0)  // 二进制拆分
    {
        m -= x;
        a[++cnt] = x;
        x <<= 1;
    }
    if(m!=0)  a[++cnt] = m;     //多余部分处理
    cout<<cnt<<endl;
    sort(a + 1, a + cnt + 1);
    for(int i = 1; i <= cnt; ++i)
    {
        if(a[i] == a[i + 1] && a[i] != 1) a[i]--, a[i + 1]++;
        cout<<a[i]<<" ";        // 打印拆分方案
    }
    return 0;
}
posted @ 2019-08-30 21:06  颓废の子乃酱  阅读(143)  评论(0编辑  收藏  举报