CF1348 D. Phoenix and Science

CF1348 D. Phoenix and Science

Question

一开始有1个细菌,他的权值为1。白天的时候1个细菌可以分裂成2个,也可以不分裂,晚上的时候1个细菌会增加权值1,求最少要多少天能够到达所有权值的和恰好为n,并且给出对应n天每天有几个细菌要分裂。

Solution

设需要 T T 天。
最快的增加方法为每次所有细菌分裂为 2 2 个,晚上加上分裂后细菌的数量,那么 T = l o g 2 ( n ) T=log_2(n)
我们构造一个满足 T = l o g 2 ( n ) T=log_2(n) 的方案即可。
细菌每天增加的个数最大为 已有细菌的个数*2,但是很容易超过 n n 而不是恰好等于 n n ,下面想办法让细菌的天数能恰好等于n。
细菌增加的个数取 m i n = ( , 2 j ) min=(\frac{还需要的权值}{能增加的次数},2j)

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 1e9 + 7;
const ll  maxn = 1e6 + 5;
const int N = 30 + 5;

void solve(){
	int n;cin>>n;
	int ans=log2(n);
	cout<<ans<<'\n';
	for(int i=0,j=1;i<ans;i++){//j为细菌的个数
		n-=j;//n表示还需要多少个权值
		int k=min(n/(ans-i),2*j);//细菌堆数最少要几个
		cout<<k-j<<" \n"[i==ans-1];//增加的权值为k,总的细菌个数为k,然而其中有j部分为就算不分裂也会产生的已有细菌个数
		j=k;//更新已有细菌个数
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Meulsama/article/details/105885938