2021トレーニングリーグウォームアップトレーニングゲーム2J.owest Common Ancestor

トピックリンク

主なアイデア:完全なバイナリツリーは、あなたが2つの数の最も近い共通の祖先(LCA)を見つけてみましょう。


アイデア:まず、バイナリの性質を理解しましょう。
ここに画像の説明を挿入します
ルートは1から始まるため、少し醜いです。xである点がある場合、その左の子は2 ∗ xです。 2 * x2x、そして彼の子供は2 ∗ x + 1 2 * x + 12バツ+1.次に、バイナリと組み合わせると、左のサブツリーが次のビット0の場合は1ビット左にシフトし、それ以外の場合は1になります。したがって、ポイントのサブツリーを左にシフトする必要があることがわかります。 2進数です(2進数)の接頭辞は最も近い共通の祖先(LCA)であり、2進数と16進数の関係は、16進数を4桁の2進数に変換できることです。次に、最初に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