如果下降的过程中某一次休息了,然后又有几次是上升的,那么那几次上升可以留着,在休息的时候上升,抵消掉休息花的时间。
init【id】是第一个大于p-q的1 + 2+ 4 + 8 + 16....的和
。对于p>q的情况有两种,一种是先往下init[id-1],再往下(x-init[id-1]), 另外一种是先往上(init【id-1】-x),再往下id步, 第一种是对的,,第二种有问题,应该要先下在上,先下id步,再往上,min【(init【id-1】-x),y】步,因为下降过程中不会小于0,这样可以节省向上的步数
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
typedef long long ll;
const ll mod=(1e9)+7;
int a[1005];
ll init[50];
ll dfs(ll x,ll y,ll step,ll stop)
{
if (x==y)return 0;
int id=upper_bound(init+1,init+1+40,x-y)-init;
if (init[id-1]==x-y)
{
return step+id-1;
}
ll up=min(y,init[id]-(x-y));
ll ansup=id+max(0LL,up-stop);
return min(step+ansup,dfs(x-init[id-1],y,step+id,stop+1 ) );
}
int main()
{
// freopen("out.txt","w",stdout);
init[0]=0;
init[1]=1;
for (int i=2; i<=40; i++)
init[i]=init[i-1]+(1<<(i-1));
/* for (int i=1;i<=30;i++)
printf("%lld\n",init[i]);*/
int t;
cin>>t;
ll q,p;
while (t--)
//for (int p=0;p<=100;p++)
// for (int q=0;q<p;q++)
// for (int dis=1; dis<=100; dis++)
{
scanf("%lld%lld",&p,&q);
if (p<=q)
{
printf("%lld\n",q-p);
continue;
}
ll ans=dfs( p,q,0,0);
printf("%lld\n",ans);
}
return 0;
}