Loading

Codeforces Round #638 D. Phoenix and Science(贪心/思维好题)

Phoenix has decided to become a scientist! He is currently investigating the growth of bacteria.

Initially, on day 11, there is one bacterium with mass 11.

Every day, some number of bacteria will split (possibly zero or all). When a bacterium of mass mm splits, it becomes two bacteria of mass m2m2 each. For example, a bacterium of mass 33 can split into two bacteria of mass 1.51.5.

Also, every night, the mass of every bacteria will increase by one.

Phoenix is wondering if it is possible for the total mass of all the bacteria to be exactly nn. If it is possible, he is interested in the way to obtain that mass using the minimum possible number of nights. Help him become the best scientist!

Input

The input consists of multiple test cases. The first line contains an integer tt (1t10001≤t≤1000) — the number of test cases.

The first line of each test case contains an integer nn (2n1092≤n≤109) — the sum of bacteria masses that Phoenix is interested in.

Output

For each test case, if there is no way for the bacteria to exactly achieve total mass nn, print -1. Otherwise, print two lines.

The first line should contain an integer dd  — the minimum number of nights needed.

The next line should contain dd integers, with the ii-th integer representing the number of bacteria that should split on the ii-th day.

If there are multiple solutions, print any.

Example
Input
Copy
3
9
11
2
Output
Copy
3
1 0 2 
3
1 1 2
1
0 
//

对于每一天来说,细菌先分裂再增加mass。假设每晚细菌的mass不增加的话,最终的mass之和肯定还是1,所以说只需要考虑增加的mass。
要达到题目所说的最快,肯定是希望每一个细菌在每天都分裂(指数增长)。
这样可以构造一个序列20,21,22...2x(序列的和小于等于n),1...x代表天数,序列的每一项的含义可以认为是这一天的细菌数。
而这个序列的和就是总的mass值,因为每天晚上每个细菌的mass加1.

这样的话,假设序列和恰好等于n,这无疑是最少的天数,如果不等的话,把n-sum插入序列中再由小到大排序,这样比sum恰好等于n时的天数多1.
可以这么理解,比如对于2i,n-sum,2i+1 第i天只有部分细菌分裂,使得第i+1天的个数到达n-sum,第i+1天的n-sum个细菌再部分分裂使得第i+2天细菌个数达到2i+1从而完成原来方案的无缝衔接,显然这也是最优情况。
输出的话直接输出构造出来的序列的差分序列即可,因为增加的细菌的个数就是分裂的细菌的个数。
#include <bits/stdc++.h>
using namespace std;
int n;
int fpow(int a,int b)
{
    int ans=1;
    for(;b;b>>=1)
    {
        if(b&1)ans*=a;
        a*=a;
    }
    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        int sum=0,day=0,i;
        vector<int>v;
        v.push_back(0);
        while(1)
        {
            int temp=fpow(2,day);
            if(sum+temp>n)
            {
                day--;
                break;
            }
            sum+=temp;
            v.push_back(temp);
            day++;
        }
        if(sum!=n)
        {
            v.push_back(n-sum);
            sort(v.begin(),v.end());
            cout<<day+1<<endl;
        }
        else
        {
            cout<<day<<endl;
        }
        for(i=1;i<v.size()-1;i++)
        {
            cout<<v[i+1]-v[i]<<' ';
        }
        cout<<endl;
    }
    return 0;
}

 

posted @ 2020-05-02 16:55  脂环  阅读(323)  评论(0编辑  收藏  举报