CodeForces_1348D Phoenix and Science(数论)

Phoenix and Science

time limit per test:2 seconds
memory limit per test:256 megabytes
Problem Description

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

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

Every day, some number of bacteria will split (possibly zero or all). When a bacterium of mass m splits, it becomes two bacteria of mass m 2 \frac{m}{2} 2m each. For example, a bacterium of mass 3 can split into two bacteria of mass 1.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 n. 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 t ( 1 ≤ t ≤ 1000 1≤t≤1000 1t1000) — the number of test cases.

The first line of each test case contains an integer n ( 2 ≤ n ≤ 1 0 9 2≤n≤10^9 2n109) — 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 n, print -1. Otherwise, print two lines.

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

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

If there are multiple solutions, print any.

Sample Input

3
9
11
2

Sample Output

3
1 0 2
3
1 1 2
1
0

题意

初始有一个质量为1的细胞,每天可以选择一部分细胞将其分裂为两个,质量为m个细胞会被分裂为两个质量为 m 2 \frac{m}{2} 2m的细胞。在每天的晚上,所有的细胞质量都会加1。
求是否存在分裂方案使细胞质量和为n,如果有输出需要天数最少的一种方案即可。

题解

可以发现实际上细胞的分裂,质量上的变化对结果并无影响,数量上的变化会对结果产生影响,所以只考虑,分裂后的细胞数量问题。
显然解是一定存在的,不分裂,n-1天质量和即为n。但是要求天数最少,考虑每天都将所有的细胞进行分裂。那么第 i i i天,细胞质量和最大为 2 i + 1 − 1 2^{i+1}-1 2i+11。求出满足 n ≤ 2 i + 1 n \le 2^{i+1} n2i+1的最小的 i i i,记为m,m即为最少的天数。
方案:将分裂看做原细胞质量不变,增加一个质量为0的新细胞(对细胞质量的和而言,他和原方案是一样的)。已知最少天数为m,则在第 i i i天产生的新细胞在第m天质量为 m − i + 1 m-i+1 mi+1。从第一天开始,枚举每天产生的新细胞数量即可。注意每天产生的新细胞的数量需小于等于之前的细胞数量。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-6
 
using namespace std;
typedef long long LL;   
typedef pair<int, int> P;
const int maxn = 200100;
const int mod = 1000000007;
int a[maxn];

int main()
{
    int t, n, m, i, j, k;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(i=1;;i++)
            if(n < (1<<(i+1))){
                m = i;break;
            }
        int x = m+1, sum = 1;
        for(i=1;i<=m;i++){
            j = m-i+1;
            a[i] = min(sum, (n-x)/j);
            x += a[i]*j;
            sum += a[i];
        }
        printf("%d\n", m);
        for(j=1;j<m;j++)
            printf("%d ", a[j]);
        printf("%d\n", a[m]);
    }
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值