主要思路:二进制拆分。
先将 (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;
}