1 条题解

  • 0
    @ 2025-8-24 23:17:24

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar FeiYu32
    &Cute_Furina||三角洲破产学教父||目前不打算解除禁言,CSP-S保六冲七ing

    搬运于2025-08-24 23:17:24,当前版本为作者最后更新于2025-06-01 18:13:51,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    思路详解

    需要点思维的题,主要是考察二进制。

    因为 >>1<<1 这两个操作是在二进制的基础上实现的,所以我们先把 aabb 转换成二进制再考虑。

    而使用这两个运算后对原数最明显的变化就是所有数向左或向右移动一位,如果溢出,就会导致消失一位,且移动后留下的空位以 00 补缺。于是在经历多次操作后,我们就能让 aa 的二进制形式前后各消失几位,因为前导零不影响二进制转十进制的计算,后导零可以通过右移来使其消失,从而修改 aa 的十进制数值。

    又因为二进制相等的两个数相等,所以只需要通过删去 aa 的二进制形式的前后几位,使其与 bb 的二进制形式相等就能完成任务。换句话说,只要 bb 的二进制形式是 aa 的二进制形式的子串即可完成任务。

    写完代码提交后我们就会发现只能获得 1010 分,还不如特殊性质获得的 2020 分多。问题就出在 bb 的二进制形式的后导零上。因为左移可以增加后导零,而在判断是否为子串的过程中可能会被 aa 的二进制形式中的其他位干扰,所以要提前去掉 bb 的二进制形式的后导零再进行判断子串的操作。

    然后就可以获得 7070 分。注意到 aabb 的上限到达了 2642^{64},所以 long long 肯定会爆,因此需要用 __int128来代替它,这里我使用重载运算符来读入,这样就能获得满分了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    long long t;
    std::istream& operator>>(std::istream& is, __int128& n)
    {
        string s;
        is>>s;
        n=0;
        bool negative=false;
        size_t start=0;
        if (s[0]=='-')
        {
            negative=true;
            start=1;
        }
        for(size_t i=start;i<s.size();i++)
        {
            n=n*10+(s[i]-'0');
        }
        if(negative)n=-n;
        return is;
    }
    int main()
    {
        cin>>t;
        for(int i=1;i<=t;i++)
        {
            __int128 a,b;
            long long c[100009],d[100009],e=0,f=0,ok1=0,qd0=1;
            cin>>a>>b;
            for(;a>0;)
            {
                e++;
                c[e]=a%2;
                a/=2;
            }
            for(;b>0;)
            {
                if(b%2!=0||qd0==0)
                {
                    f++;
                    d[f]=b%2;
                    qd0=0;
                }
                b/=2;
            }
            for(int j=1;j<=e-f+1;j++)
            {
                int ok=1;
                for(int k=1;k<=f;k++)
                {
                    if(d[k]!=c[j+k-1]){ok=0;break;}
                }
                if(ok==1){cout<<"Yes"<<endl;ok1=1;break;}
            }
            if(ok1==0)cout<<"No"<<endl;
        }
    }
    

    完结撒花!

    • 1

    信息

    ID
    12400
    时间
    2000ms
    内存
    512MiB
    难度
    2
    标签
    递交数
    0
    已通过
    0
    上传者