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;
}