题目链接:http://codeforces.com/contest/916/problem/B
思路:先拆成二进制,要满足最高位最小,即最大的能拆完就拆完,否则从最小的数一个个开始拆,详见代码。
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#define LL long long
#define maxn 100005
#define MOD 1000000000+7
using namespace std;
int v[maxn],ans[maxn];
int main()
{
LL n,k;
cin>>n>>k;
int index,cnt;
index=cnt=0;
while(n)//变为二进制数
{
if(n%2==1)
cnt++;
v[index++]=n%2;
n/=2;
}
if(cnt>k)//如果二进制数的1的个数大于k,则不可能
{
puts("No");
return 0;
}
puts("Yes");
int mini;//mini是高位拆分不行之后应该从最低数位为1的位置开始拆分
for(int i=0;i<index;i++)
{
ans[i]=v[index-i-1];
if(ans[i])
mini=i;
}
for(int i=0;;i++)
{
if(cnt==k) break;
if(k-cnt>=ans[i])
{
cnt+=ans[i];
ans[i+1]+=ans[i]*2;
ans[i]=0;
}
else break;
if(i+1>mini)//更新mini
mini=i+1;
}
while(cnt!=k)//如果高位拆分不成功进行此操作,从mini开始拆分
{
cnt++;
ans[mini]--;
ans[mini+1]+=2;
mini++;
}
int t;
for(int i=0;i<=mini;i++)//从第一位到最后拆分到的那位遍历,然后看每个位置上的1的个数
{
while(ans[i])
{
ans[i]--;
t=index-1-i;
cout << t << ' ';
}
}
cout << endl;
return 0;
}