ZCMU—1946

来源:互联网 发布:壁虎数据恢复怎么用 编辑:程序博客网 时间:2024/05/16 19:11

1946: Who is stupid?

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 4  Solved: 1
[Submit][Status][Web Board]

Description

xh 和 hx 经常互相嘲笑对方智商低而打架,cc为了让hx和xh和谐的变成好基友,cc要操作使得hx 和xh的智商变成一样。

题目给出hx和xh的智商x,y(0<=x, y<=1e9) , cc每一次操作都能改变hx的智商,cc的神奇的操作有3个选择

1.增加一点hx的智商

2.减少hx的智商 z点 (下一次操作cc就可以减少2*z点智商,若上一次cc增加了一点hx的智商或者选择休息,则这次只能减少1点,第一次操作也只能减少1点智商)

3.休息(休息也算一种操作)

cc想知道做少操作几次才能使hx和xh变成好基友?

Input

输入包含T组数据(1 <= T <= 300000)

每组数据包含x,y

Output

输出最小的操作次数

Sample Input

2
1 5
7 3

Sample Output

4
4

HINT

智商不能小于0


【分析】

对智商x,y可以考虑,当x<=y时只能进行+1操作,所以ans=y-x;
否则就要考虑如何减,稍微考虑一下可以发现,肯定是一次性减,减到x<=y,那么答案就是进行减智商的步数t+y-x;

但是有可能是减到最靠近y的但是比y大的那个数,然后停一步,接着从1开始减,然后减到x<=y,答案如上,
类推,也就是可能需要多次连续的减智商,再+1补回来。
所以只要去搜一下减的次数就可以了,另外考虑一点,因为如果要打断连续的减智商,需要一部休息(stop),但是这一步stop用来做之后需要的y-x步的+1操作也是可以的,所以记录一下stop,在之后考虑+1操作的时候先用stop次数去补。别的问题不大...记得10^9需要考虑long long 防止(1<<t)炸掉
【代码】
#include <cstdio>#include <iostream>#include <algorithm>#include <cmath>using namespace std;long long x,y;long long dfs(long long now,long long deep,long long stop){if (now==y) return deep;long long t=0;while (now-(1<<t)+1>y) t++;if (now-(1<<t)+1==y) return deep+t;long long ans=y-max(0LL,now-(1<<t)+1);ans=deep+t+max(0LL,ans-stop);ans=min(ans,dfs(now-(1<<(t-1))+1,deep+t,stop+1));return ans;}int main(){int pp;scanf("%d",&pp);while (pp--){scanf("%lld%lld",&x,&y);if (x<=y)printf("%lld\n",y-x);else printf("%lld\n",dfs(x,0,0));}return 0;}