CF1271E Common Number 题解

CF1271E

简单题。

首先直接从 $k$ 入手是不好做的,于是从每个值进行考虑。

发现能到达 $x$ 的点有两种情况,分类讨论一下。

$x$ 为奇数时,上一个数一定是 $2x$。

$x$ 为偶数时,上一个数为 $x+1$ 或 $2x$。

奇数一次过后就会变为偶数,所以对偶数再推一步 $2x+2,2x+1,4x$。

发现前两项和后一项成倍数的关系,对前两项再做一遍,使得 $x$ 前面的系数相同 $2x+3,4x+4,4x+2$。把所有的数塞到一个集合里面就可以发现一些了:$\{x,x+1,2x,2x+1,2x+2,2x+3,4x+1,4x+2,4x+4\dots\}$。$4x$ 和 $2x$ 那里不是很像是因为还没有将所有的 $2x+k$ 再推一步。

结论就容易得到了,即对于偶数 $x$,$2^kx$ 这一层会有 $2^{k+1}$ 个数有贡献,暴力计算就可以。

显然的,在 $x$ 为偶数时是有单调性的。奇数同理。虽然当 $x$ 为偶数时,$x\in path_j$ 的 $j$ 的个数一定不劣于奇数的情况。但因为是求最后的 $x$ 的 $\max$,所以奇数是有可能成为答案的,两遍二分即可。

代码:

ll n,k;
ll check(ll x){
    int base=0;ll res=0;
    if(x&1){
        int len=0;
        for(;(x<<base)<=n;base++,len++)res+=min((x<<base)+(1ll<<len)-1,n)-(x<<base)+1;
    }else{
        int len=1;
        for(;(x<<base)<=n;base++,len++)res+=min((x<<base)+(1ll<<len)-1,n)-(x<<base)+1;
    }
    return res;
}
int main(){
    cin>>n>>k;
    ll l=1,r=n/2+(n&1);
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(2*mid)>=k)l=mid+1;
        else r=mid-1;
    }
    ll res=r*2;
    l=1,r=n/2+(n&1);
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(2*mid-1)>=k)l=mid+1;
        else r=mid-1;
    }
    res=max(res,r*2-1);
    cout<<res<<"\n";
    return 0;
}
posted @ 2023-10-18 10:43  Pengzt  阅读(4)  评论(0编辑  收藏  举报  来源