题目大意:
初始时有一个细胞有一个单位的重量,每个细胞每天增长1个单位的重量,每天你可以选择任意数目的细胞让他们分裂,即一个变成两个,对总重量无影响,但之后分裂的细胞也会每天增长(先分裂,再增长)。问最少增长几次,可以使总重量恰好为n(n<=1e9)。
输入:
多组测试,t次,每次输入一整数n。
输出:
输出最少增长次数d,接下来d个整数,表示每次增长的个数。
设第i天个数为ai,则相当于求一个序列a,满足 a i a_i ai<= a i + 1 a_{i+1} ai+1<= 2 ∗ a i 2*a_i 2∗ai,sum(a)=n且序列长度最短。
按照1,2, 2 2 2^2 22,…, 2 k 2^k 2k来构建,使得sum<=n。若sum=n, a i a_i ai就是每天个数,否则,将n-sum加入序列,重新排序,即为结果。
题目要求增长次数,输出a.size-1,以及 a i − a i − 1 a_i-a_{i-1} ai−ai−1。
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<vector>
#define cl (k<<1)
#define cr (k<<1|1)
#define Mid ((a[k].l+a[k].r)>>1)
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
#define bug printf("???\n")
typedef long long LL;
const int Inf=0x3f3f3f3f;
const double eps=1e-7;
const int maxn=-1;
void solve(int n){
vector<LL>ve;
LL sum=0;
for(int i=0; sum+(1<<i) <= n; i++){
sum += 1<<i;
ve.push_back(1<<i);
}
if(sum!=n){
ve.push_back(n-sum);
sort(ve.begin(), ve.end());
}
printf("%d\n",ve.size()-1);
for(int i=1; i<ve.size(); i++){
printf("%d ",ve[i]-ve[i-1]);
}
printf("\n");
}
int main()
{
int T;
cin>>T;
while(T--){
int n;
cin>>n;
solve(n);
}
}