【链接】 我是链接,点我呀:)
【题意】
【题解】
把n分解成二进制的形式。 n=2^a0+2^a1+...+2^a[q-1] 则固定就是长度为q的序列。 要想扩展为长为k的序列。 可以把2^x转化为2^(x-1)+2^(x-1)的形式. 这样序列的长度就+1了 它要求max{ai}最小 那么我们可以枚举ai的最大值是什么->i (递减着枚举) 然后比i大的ai都换成两个ai-1的形式。 然后看看序列的长度是否小于等于k; 如果小于k的话。 就把min{ai}分解成两个min{ai}-1 这样可以尽量让max{ai}==i的情况下,字典序尽量大。 这样长度递增1. 重复上述步骤。直到长度变为k.然后枚举最大值为i-1,i-2...
【代码】
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 64;
ll n;
int k,a[N+10];
map<int,ll> cnt,cnt1;
vector<int> v;
int main(){
#ifdef LOCAL_DEFINE
freopen("rush_in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0),cin.tie(0);
cin >> n >> k;
while (n){
a[0]++;
a[a[0]] = n&1;
n>>=1;
}
ll now = 0;
for (int i = a[0];i >= 1;i--)
if (a[i]){
now++;
cnt[i-1]++;
}
for (int j = 0;j<=N;j++) cnt1[j] = cnt[j];
int ma = a[0]-1;
ll tlen = now;
for (int i = ma; ;i--){
cnt.clear();
for (int j = 0;j <= N;j++)
cnt[j] = cnt1[j];
now = tlen;
for (int j=N;j>=i+1;j--){
now+=cnt[j];
cnt[j-1]+=2*cnt[j];
cnt[j] = 0;
}
/*cout <<"i="<<i<<endl;
cout <<now<<endl;
*/
if (now>k) break;
int last = -100000;
while (now<k){
for (int j = last;j <= N;j++){
if (cnt[j]>0){
cnt[j]--;
cnt[j-1]+=2;
now++;
last = j-1;
break;
}
}
}
v.clear();
for (int j = N;j>=last;j--)
for (int l = 1;l <= cnt[j];l++){
v.push_back(j);
}
now = tlen;
}
if (v.empty()){
cout <<"No"<<endl;
}else{
cout <<"Yes"<<endl;
for (int i = 0;i < (int) v.size();i++){
cout <<v[i]<<' ';
}
}
return 0;
}