题意
给你n(LL),k(1e5)让你将n分成k个数 2的ki的幂次之和 == n
要求在 最大的数尽量小 的条件下 字典序尽量大。
思路
将n映射成二进制0 1标注,if(num >= k) 没有答案
else 从最高位开始向下拆分(这是因为要使最大值最小) 拆到出现最小的最大值不再拆分(这是因为要使字典序尽量大),此时从最小值开始依次拆分,从而保证了字典序的要求。【这个过程写的有点恼火 啊我太菜了】
ACcode
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int MaxN = 1e5 + 5;
LL n,k;
int w[MaxN];
priority_queue<int> que,q;
int main()
{
scanf("%lld %lld",&n,&k);
LL N = n;
int cnt = -1,t = 0;
while(N){
LL cur = N % 2LL;
++cnt;
if(cur){
t++;
// cout << cnt << "#\n";
que.push(cnt);
q.push(cnt);
}
N /= 2;
}
if(t > k){
printf("No\n");
return 0;
}
LL haha = k - t;
//字典序最大 首min
LL HH = haha;
while(HH--){
int cur = q.top();
q.pop();
q.push(cur - 1);
q.push(cur - 1);
}
int Jd = q.top();
while(haha--){
int cur = que.top();
if(Jd == cur) break;
que.pop();
que.push(cur - 1);
que.push(cur - 1);
}
int i = 0;
while(!que.empty()){
w[++i] = que.top();
que.pop();
}
while(i < k){
w[i] -= 1;
w[++i] = w[i - 1];
}
printf("Yes\n");
for(int i = 1;i <= k; i++) printf("%d ",w[i]);
printf("\n");
}