题目https://www.luogu.com.cn/problem/P11785赛时写出来的,可惜报名晚了一些(大概 1h),卡在第 363 名。
首先,我们对 进行二进制拆分,拆成若干个二的幂相加的形式。
随后,如果这个序列的长度本身就是二的幂次方,直接输出。
否则,从最小的不是 的数开始拆分,每次拆成这个数的一半(有两个),序列长度加
。
一旦序列长度达到了二的幂次方,直接输出结果。
实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n;
vector<int>v,ans;
int check(int x){
int tmp=__lg(x);
return (1<<tmp)==x;
}
void BIT(int x){
v.clear(),ans.clear();
string s="";
while(x){
s+=to_string(x%2);
x/=2;
}
priority_queue<int,vector<int>,greater<int>>q;
int pr=1;
for(auto z:s){
if(z=='1'){
v.push_back(pr);
q.push(pr);
}
pr*=2;
}
if(check(v.size())){
for(auto z:v){
cout<<z<<' ';
}
}else{
int suv=v.size();
while(true){
if(q.top()==1){
ans.push_back(1);
q.pop();
}else{
break;
}
}
while(true){
if(q.top()==1){
q.pop();
ans.push_back(1);
continue;
}
suv++;
int p=q.top();
q.pop();
q.push(p/2),q.push(p/2);
if(check(suv)){
break;
}
}
while(q.size()&&q.top()==1){
ans.push_back(1);
q.pop();
}
for(auto z:ans){
cout<<z<<' ';
}
while(q.size()){
cout<<q.top()<<' ';
q.pop();
}
}
cout<<'\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
for(cin>>t;t;t--){
cin>>n;
BIT(n);
}
return 0;
}