CF1348 D. Phoenix and Science
Question
一开始有1个细菌,他的权值为1。白天的时候1个细菌可以分裂成2个,也可以不分裂,晚上的时候1个细菌会增加权值1,求最少要多少天能够到达所有权值的和恰好为n,并且给出对应n天每天有几个细菌要分裂。
Solution
设需要 T天。
最快的增加方法为每次所有细菌分裂为 2个,晚上加上分裂后细菌的数量,那么 T=log2(n)。
我们构造一个满足 T=log2(n)的方案即可。
细菌每天增加的个数最大为 已有细菌的个数*2,但是很容易超过 n而不是恰好等于 n,下面想办法让细菌的天数能恰好等于n。
细菌增加的个数取 min=(能增加的次数还需要的权值,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;
}