题目大意:

给你两个数a,b。然后对于a可以连续进行减操作,每次减操作减去的数为上一次减操作减去的数的2倍,从减1开始,或者也可以对a进行+1操作或者不操作,之后在进行减操作就是重新从减1开始了。
现在有300,000组测试数据,每组测试数据两个数 0 < a,b < 10e9 。

分析:

如果单纯的用搜索,因为有300,000组测试数据,应该就会超时。所以能接受的每一组测试数据的时间复杂度应该就是:O(log|a-b|)。

代码:

#include<iostream>
#include<stdio.h>
#include<queue> 
#include<math.h>
using namespace std;
long long int pf[100]={0};//2的i次方=pf[i] 
void init()
{
    for(int i=0;i<=31;i++)
    {
        pf[i]=1;
        pf[i]=pf[i]<<i;
        pf[i]--;
    }
}
long long int f(long long int a,long long int b,int x)//从a通过变换规则1到b,在之前已经进行了x次连续加的操作之后,需要操作的最少次数 
{
    if(a<=b)return (b-a)>(x-1)?(b-a):(x-1);
    int t=0;int k=a-b;
    while(1)
    {
        if(k<=pf[t])break;
        t++;
    }
    if(pf[t]==k)return x+t;
    //cout<<"min(f("<<a+pf[t]-1<<","<<b<<","<<x+1<<")"<<"+"<<t<<","<<"f("<<a+pf[t-1]-1<<","<<b<<","<<x+1<<")+"<<t-1<<");";
    return min(f(0>a-pf[t]?0:(a-pf[t]),b,x+1)+t,f(a-pf[t-1],b,x+1)+t-1);
}

int main()
{
    long long int a,b;//从a到b
    int n;
    init();
    scanf("%d",&n);
    while(n--)
    {
        scanf("%lld%lld",&a,&b);
        if(a<=b)
        {
            printf("%lld\n",b-a);
            continue;
        }
        printf("%lld\n",f(a,b,0));
    }
}