Searching for Soulmates S 题解

链接

这里的 \(x\) 可以乘 2 或除 2 或加 1

也相当于 \(y\) 可以除 2 或乘 21

这题我们发现每一个数都是可以任意的到达另一个数。因为每一个数都可以到达 1 ,这里只需要用到除和加即可,若奇数则加,否则除。

可以让 \(x\) 做转移到 1 的过程,再从 \(y\) 这一个点到 \(x'\) 的最小距离即可这里只能使用减和除,若使用乘那还不如直接在 \(x'\) 的基础上进行继续向 1 转移。

把这个由 \(y \rightarrow x\) 的最小的距离抽象成函数 \(f(x,y)\)

  • \(x'>y\)\(f(x,y)=\inf\),因为这个只能除 2 来减少 \(x'\) ,所以不可能转移。

  • \(2\times x'>y\) 这里我们不能做乘 2 操作,只能加 1 操作,之后亦是如此, \(f(x,y)=y-x\)

  • \(2\mid y\) \(f(x,y)=f(x,y/2)\)

  • \(2\nmid y\) \(f(x,y)=f(x,y-1)\)

    这样计算 \(f\) 的时间复杂度为\(O(\log a)\) 的总的时间复杂度是 \(O(\log^2a)\) 的,代码简单。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int T,x,y,ans;
    int dfs(int x,int y) {
    	if(x > y) return 1e18;
    	if(x*2 > y) return y-x;
    	return y&1? dfs(x,y-1)+1:dfs(x,y>>1)+1;
    }
    int cnt;
    signed main() {
    	scanf("%lld",&T);
    	while(T--) {
    		scanf("%lld%lld",&x,&y);
    		ans=1e18,cnt=0;
    		do{
    			ans=min(ans,cnt+dfs(x,y));
    			cnt++;
    			if(x&1)x++;
    			else x/=2;		
    		} while(x>1);
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
posted @ 2025-03-11 21:12  hnczy  阅读(48)  评论(0)    收藏  举报