题意:
多测,每一次给出一个n。一开始有n个0,每次可以选择以下两个操作执行任意次:
1.给其中一个位置,让
项变成1。
2.给出和
,使
,若al和ar都是一,且
到
的和
。那么让
到
的所有数都变成1。
问:是所有数都变成一最少要执行多少个1类型?
样例:
4
1
2
4
20
1
2
2
4
思路:
我么不难能够想到,可以把n分成许多块,每一块都放一半的1,假设分了块,每一块的长度是
,sk指的是第k块的长度。那么发现,每个块互相是不影响的。所以需要再改进。
我们来看一下下面这个例子
我们在第一个和第四个上面放1,在第十个上面放1,在最后一个上面放1,
然后对
1到4执行而操作2
这个操作使原来不可以执行2类型操作的1到10变得可以执行二类型操作。
1到10执行操作2
这个操作又使这个区间可以变成一
那么做法便推导出来,一开始在头部放一个1。
然和重复执行以下操作直到成为一的数量等于甚至大于n:
1.假设放了a个连续一(这种方法的一是连续的,且从第一个位置开始连续),在(a+1)*2位置放一个1,然后对1~(a+1)*2执行二类型操作(下面解释为什么可以执行二操作),现在就有2*(a+1)个一。然和更新a为2*(a+1),那么下一次操作的a就是这次的(a+1)*2了。
解释:1~(a+1)*2的长度是2*(a+1),原先放了a个一,现在有a+1个,正好有一半。
代码如下(不要无脑复制):
#include <bits/stdc++.h>
#define int long long//坏习惯改不掉了
#define rep(i,a,b) for(int i=a;i<b;i++)
#define REP(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
void solve(){
int n,cnt=1,sum=1;//分别是执行一操作的数量和总1的数量
cin>>n;
while(n>sum){
cnt++;//放1
sum=2*(sum+1);//更新1的数量
}
cout<<cnt<<"\n";
}
signed main(){
int T=1;
cin>>T;
while(T--)solve();
return 0;
}
498

被折叠的 条评论
为什么被折叠?



