CF1271E Common Number 题解
简单题。
首先直接从 $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;
}