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

题目链接

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


思路: 首先带你了解一下二进制的性质:
在这里插入图片描述
有点丑将就看吧,因为根 是从1开始的,所以如果有一个点是x那么他的左孩子是 2 ∗ x 2*x 2x,而他的有孩子是 2 ∗ x + 1 2*x+1 2x+1.那么再结合二进制也就是左移一位,如果左子树那么就是后一位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 mst(x, a) memset( x,a,sizeof(x) )
#define rep(i, a, b) for(int i=(a);i<=(b);++i)
#define dep(i, a, b) for(int i=(a);i>=(b);--i)

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;

}


猜你喜欢

转载自blog.csdn.net/weixin_45911397/article/details/114799054