​题目链接​

题目大意: 一个16进制的完全二叉树,让你求两个数的最近公共祖先(LCA).


思路: 首先带你了解一下二进制的性质:

2021年度训练联盟热身训练赛第二场J.owest Common Ancestor_#define


有点丑将就看吧,因为根 是从1开始的,所以如果有一个点是x那么他的左孩子是2021年度训练联盟热身训练赛第二场J.owest Common Ancestor_i++_02,而他的有孩子是2021年度训练联盟热身训练赛第二场J.owest Common Ancestor_#define_03.那么再结合二进制也就是左移一位,如果左子树那么就是后一位0,否则为1,所以我们可以知道一个点的子树一定是由他左移过来的.就是两个数(二进制)的前缀就是他们的最近公共祖先(LCA),而二进制与16进制的关系就是一位16进制可以转化成4位二进制数,那么我们就可以先把16进制转化成2进制,再把2进制转化成16进制.注意不要前缀0.最后要先加上是因为防止最后不够4位而丢了.最后还要消去前缀0.

#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 +7 ;
const ll mod = 1e9 + 7;

#define
#define
#define

inline ll read() {
ll x = 0;
bool f = 0;
char ch = getchar();
while (ch < '0' || '9' < ch)
f |= ch == '-', ch = getchar();
while ('0' <= ch && ch <= '9')
x = x * 10 + ch - '0', ch = getchar();
return f ? -x : x;
}

void out(ll x) {
int stackk[20];
if (x < 0) {
putchar('-');
x = -x;
}
if (!x) {
putchar('0');
return;
}
int top = 0;
while (x)
stackk[++top] = x % 10, x /= 10;
while (top)
putchar(stackk[top--] + '0');
}
ll qpow(ll a,ll b) {
ll ans=1;
while(b) {
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}


string str,s;
map<char,string >mp;
map<string,char >mpp;
int main() {
int _=read();
mp['0']="0000";
mp['1']="0001";
mp['2']="0010";
mp['3']="0011";
mp['4']="0100";
mp['5']="0101";
mp['6']="0110";
mp['7']="0111";
mp['8']="1000";
mp['9']="1001";
mp['a']="1010";
mp['b']="1011";
mp['c']="1100";
mp['d']="1101";
mp['e']="1110";
mp['f']="1111";

mpp["0000"]='0';
mpp["0001"]='1';
mpp["0010"]='2';
mpp["0011"]='3';
mpp["0100"]='4';
mpp["0101"]='5';
mpp["0110"]='6';
mpp["0111"]='7';
mpp["1000"]='8';
mpp["1001"]='9';
mpp["1010"]='a';
mpp["1011"]='b';
mpp["1100"]='c';
mpp["1101"]='d';
mpp["1110"]='e';
mpp["1111"]='f';
ll T=0;
while(_--) {
cin>>str>>s;
string ans_str,ans_s;
string ans,ans1;
for(int i=0; i<str.size(); i++) {
ans_str+=mp[str[i]];
}
for(int i=0; i<s.size(); i++) {
ans_s+=mp[s[i]];
}
for(int i=0; i<ans_str.size(); i++) {
if(ans_str[i]=='0') {
continue;
} else {
ans_str=ans_str.substr(i,ans_str.size()-i);
break;
}
}
for(int i=0; i<ans_s.size(); i++) {
if(ans_s[i]=='0') {
continue;
} else {
ans_s=ans_s.substr(i,ans_s.size()-i);
break;
}
}

///cout<<ans_str<<endl;
///cout<<ans_s<<endl;
for(int i=0; i<min(ans_str.size(),ans_s.size()); i++) {
if(ans_str[i]==ans_s[i]) {
ans=ans+ans_str[i];
} else break;
}

ans="00000"+ans;///这个地方出过一次锅
for(int i=ans.size()-1; i>=3; i-=4) {
string q=ans.substr(i-3,4);
ans1=mpp[q]+ans1;
}

for(int i=0; i<ans1.size(); i++) {
if(ans1[i]=='0') {
continue;
} else {
ans1=ans1.substr(i,ans1.size()-i);
break;
}
}
printf("Case #%lld: ",++T);
cout<<ans1<<endl<<endl;

}
return 0;

}