[HNOI2006]鬼谷子的钱袋
题面
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;
}