1 条题解

  • 0
    @ 2025-8-24 22:53:59

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Wf_yjqd
    哀酱永远的神/tyt /se /qq!!!

    搬运于2025-08-24 22:53:59,当前版本为作者最后更新于2023-09-23 11:29:49,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    官方题解。

    自评难度介于黄和绿之间。

    暂时没考虑到其他做法。


    Subtask 0\text{Subtask 0}

    对于每次询问暴搜。

    Subtask 1\text{Subtask 1}

    考虑离线处理,将所有询问按 kk 从小到大排序,然后一次 dp 出所有答案。

    或者直接记忆化搜索。

    复杂度为 O(n2)\operatorname{O}(n^2)

    注:以上复杂度中的 nn 仅表示题面中 n,kn,k 的数量级。

    Subtask 2\text{Subtask 2}

    考虑求出达到 nn 的最小次数,然后尝试在过程中浪费一些操作以达到 kk 次。

    首先特判 n=0,1n=0,1 的情况。

    n1n\ge 1 时,我们可以通过 1×21=11\times2-1=1 这样的操作浪费掉任意偶数次。

    n2n\ge 2 时,我们还可以通过 2×211=22\times 2-1-1=2 这样的操作浪费掉 33 次。

    显然可以凑出大于 11 的任意整数。

    考虑能否浪费 11 次,显然只有 a×211=(a1)×2a\times2-1-1=(a-1)\times2

    如果 nn 的最短操作中不包括 (a1)×2(a-1)\times2,以上方案就无法实现。

    此时 nn 一定为 22 的幂次或 22 的幂次 1-1(最多只允许最后有一次 1-1 操作)。

    根据以上条件即可判断是否可行,复杂度 O(T×logn)\operatorname{O}(T\times\log{n})


    或许您会不知道如何求达到 nn 的最小次数,有一种较简单的思考方法。

    转换此题为一个本质完全相同的问题(也是出题人最开始想到的问题)。

    给定一个整数 nn,进行 kk 次操作,问最终能否为 11

    每次操作从以下两种中选一个:

    • aa+1a\gets a+1
    • aa2a\gets\frac{a}{2}aa 为偶数时可选)

    他们的最小次数也是一样的。

    考虑尽可能多的 aa2a\gets\frac{a}{2} 即可。


    放一下代码吧。

    30pts30pts

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll maxn=1e5+84,maxm=4e3+23;
    struct Query{
        ll k,n,id;
        bool ans;
        inline void read(ll x){
            scanf("%lld%lld",&k,&n);
            id=x;
            return ;
        }
        friend bool operator<(Query xy,Query zb){
            return xy.k<zb.k;
        }
    }q[maxn];
    ll T,j;
    bitset<maxn> ans,Next;
    inline bool cmp(Query xy,Query zb){
        return xy.id<zb.id;
    }
    int main(){
        scanf("%lld",&T);
        for(ll i=1;i<=T;i++)
            q[i].read(i);
        sort(q+1,q+T+1);
        ans[1]=1;
        j=1;
        for(int i=1;i<=q[T].k+2;i++){
            while(j<=T&&i==q[j].k+1){
                q[j].ans=ans[q[j].n]==1;
                j++;
            }
            Next.reset();
            for(int i=ans._Find_first();i!=ans.size()&&i<=maxm;i=ans._Find_next(i)){
                if(i*2<=maxm)
                    Next[i*2]=1;
                if(i>=1)
                    Next[i-1]=1;
            }
            ans=Next;
        }
        sort(q+1,q+T+1,cmp);
        for(int i=1;i<=T;i++)
            puts(q[i].ans?"Yes":"No");
        return 0;
    }
    

    100pts100pts

    // 哀太可爱辣
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll T,k,n,res,ans;
    inline ll Q(ll x){
        res=0;
        while(x!=1){
            if(x&1)
                x++;
            else
                x>>=1;
            res++;
        }
        return res;
    }
    inline bool check(ll x){
        if(x&1)
            x++;
        return (x&(-x))==x;
    }
    int main(){
        scanf("%lld",&T);
        while(T--){
            scanf("%lld%lld",&k,&n);
            if(!k)
                puts(n==1?"Yes":"No");
            else if(!n)
                puts("Yes");
            else if(n==1)
                puts(k%2==0||k>=5&&k%2?"Yes":"No");
            else{
                ans=Q(n);
                puts(ans>k||ans+1==k&&check(n)?"No":"Yes");
            }
        }
        return 0;
    }
    
    • 1

    信息

    ID
    9243
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者