[USACO22JAN] Searching for Soulmates S

洛谷[USACO22JAN] Searching for Soulmates S

题目大意

有两个数 a , b a,b a,b,你可以进行若干次将 a a a 2 2 2,除以 2 2 2(当 a a a是偶数时),或加 1 1 1,使得 a a a b b b相等。

n n n组数据。

1 ≤ n ≤ 10 , 1 ≤ a , b ≤ 1 0 18 1\leq n\leq 10,1\leq a,b\leq 10^{18} 1n10,1a,b1018


题解

我们考虑将 a a a b b b都变小,看在哪里相会(不一定要相等,相近即可,答案为两者分别的步数加上距离)。

a a a的操作如下:

  • 如果 a a a为奇数,则加 1 1 1
  • 如果 a a a为偶数,则除以 2 2 2

进行这个操作,直到 a a a变为 1 1 1。记录到达每一个值的步数,并存在 m a p map map中。

b b b的操作如下:

  • 如果 b b b为奇数,则减 1 1 1(等价于 a a a 1 1 1
  • 如果 b b b为偶数,则除以 2 2 2(等价于 a a a 2 2 2

进行这个操作,每次操作完后,在 m a p map map中去找最近的小于等于它的数,两个数的差加上两边的步数的最小值即为答案。

code

#include
using namespace std;
int n;
long long a,b,now,ans;
map<long long,long long>mp;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		ans=1e18;
		mp.clear();
		now=0;
		scanf("%lld%lld",&a,&b);
		mp[a]=0;
		while(a!=1){
			++now;
			if(a%2==1) mp[++a]=now;
			else{
				a/=2;
				mp[a]=now;
			}
		}
		now=0;
		while(b){
			auto it=mp.upper_bound(b);
			--it;
			ans=min(ans,now+abs(b-it->first)+it->second);
			++now;
			if(b%2==1) --b;
			else b/=2;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

你可能感兴趣的:(题解,题解)