洛谷[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} 1≤n≤10,1≤a,b≤1018
题解
我们考虑将 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<bits/stdc++.h>
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;
}
文章介绍了USACO22JAN比赛中的一个编程问题,寻找两个数a和b通过特定操作相等的方法。解题策略是分别减少a和b,记录每个步骤,最后找到最小的操作步数。代码示例展示了如何利用C++实现这个算法。
538

被折叠的 条评论
为什么被折叠?



