题目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;
}