鬼谷子的钱袋(lgP2320)

主要思路:二进制拆分。

先将 \(m\) 进行二进制拆分。

注意金币总数有限,也就是说拆分后可能会多出来一组。多出来的这组如果不是 \(2^n\) 就不需要考虑了,因为不会和前面的重复。

接下来考虑重复的情况,如 \(m=23\) ,可以拆为 \(1 2 4 8 8\)

于是我们直接把俩 \(8\) 变成 \(7\)\(9\)

当我们需要用 \(8\) 时,直接用 \(7+1\) 。如果还需要 \(1\),就直接用 \(9\) 。故可以保证正确性。

代码就很简单了。

#include<bits/stdc++.h>
using namespace std;
int m,ans[101],k=1;
int main()
{
	int cnt=0;
	scanf("%d",&m);
	while(k<=m)
	{
		m-=k;
		ans[++cnt]=k;
		k<<=1;
	}
	if(m) ans[++cnt]=m;
	for(int i=1;i<cnt;i++)
	{
		if(ans[i]==ans[cnt]&&ans[cnt]!=1)
		{
			ans[i]++;
			ans[cnt]--;
			break;
		}
	}
	sort(ans+1,ans+cnt+1);
	cout<<cnt<<endl;
	for(int i=1;i<=cnt;i++)
	{
		cout<<ans[i]<<" ";
	}
	return 0;
}
posted @ 2021-01-29 20:46  樱雪喵  阅读(72)  评论(0编辑  收藏  举报