牛客小白月赛122 D题x_to_y_2
题目描述
给定两个整数 x, y,你每次可以做如下两种操作之一:
- 令 x = ⌊x/2⌋(即 x 除以 2 后向下取整)。
- 选择任意一个整数 z,令 x = x | z(| 表示按位或,例如 1 | 2 = 3)。
请问最少操作几次才可以让 x 变成 y。
输入描述
本题有多组测试数据。
第一行输入一个整数 T (1≤T≤1e5),表示数据组数。
对于每组测试数据:每行输入两个整数 x, y (0≤x,y≤1e18)。
输出描述
对于每组测试数据,输出把 x 变成 y 的最小操作次数。
示例 1
输入
4
1 4
0 5
8 8
123987 444
输出
2
1
0
12
说明
对于第一组测试数据,一种操作次数最少的方式是:先用操作 2,选 z=9,令 x=1 | 9=9,然后用操作 1,令 x=⌊9/2⌋=4=y,共 2 次操作。
赛时写这道题,我猜一种构造方法,也就是每次都使用操作1,最后一次使用操作2来得到y.
证明如下

所以,我们可以通过枚举操作1的次数来找到最小的操作次数。
什么时候x可以通过一次操作2来得到y呢?我们演示一下
当x当前位置上是0时:
y的位置上无论时0还是1,我们都可以通过异或来使得x当前位变成y的当前位
当x当前位置是1时:
y的位置此时只有1才能使得x当前位变成y的当前位,如果y的当前位是0的时候就不行了。
x=0 --->y=0,1
x=1 ---->y=1
所以我们可以进行一种神奇的操作----(x&y==x),如果满足这个条件就可以让x异或上一个数字得到y
知道了这个思路代码就很简单了
附上代码
#include<bits/stdc++.h>
using namespace std;
int t;int main(){cin>>t;while(t--){long long int x,y,cnt=0;cin>>x>>y;while((x&y)!=x){x>>=1;cnt++; }if(x!=y)cnt++;cout<<cnt<<endl;}return 0;
}这个是我后来看题解写的代码
最开始我把思路交给ai,生成了一份(赛后懒得码了),处理了一些特况,时间快了将近8倍。下面也给出
#include <bits/stdc++.h>
using namespace std;using ll = unsigned long long;// 计算数字n的最高位1的位置(0-based,最低位为0)
int get_high_bit(ll n) {if (n == 0) return -1;return 63 - __builtin_clzll(n); // 利用内置函数计算前导0的个数,推导最高位
}// 检查x是否可通过右移得到y
bool can_shift(ll x, ll y) {if (y > x) return false;while (x > y) {x >>= 1;}return x == y;
}// 计算x右移到y所需的步数
int shift_steps(ll x, ll y) {int steps = 0;while (x > y) {x >>= 1;steps++;}return steps;
}// 求解最少操作次数
int solve(ll x, ll y) {if (x == y) return 0;if (y == 0) {return get_high_bit(x) + 1; // 右移到0的步数为最高位+1}if (x == 0) {return 1; // 0 | y = y,一次操作}int p = get_high_bit(x);int q = get_high_bit(y);// 检查是否可通过纯右移得到if (can_shift(x, y)) {return shift_steps(x, y);}// 需结合或操作,找最小sint s_min = max(0, p - q); // s的下界:确保x右移后高位不超过y的高位for (int s = s_min; ; s++) {ll x_shifted = x >> s;if (x_shifted > y) continue; // x右移后仍大于y,不合法// 检查x_shifted的所有1位是否在y中均为1(兼容)if ((x_shifted & y) == x_shifted) {return 1 + s; // 1次或操作 + s次右移}}
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int t;cin >> t;while (t--) {ll x, y;cin >> x >> y;cout << solve(x, y) << '\n';}return 0;
}思路本质上一样的,就是多了些特况的处理。
