题意
定义一个函数
f
(
x
)
=
x
2
(
x
=
=
e
v
e
n
)
,
f
(
x
)
=
f
(
x
−
1
)
(
x
=
=
o
d
d
)
f(x)= \frac{x}{2} (x==even),f(x)=f(x-1) (x==odd)
f(x)=2x(x==even),f(x)=f(x−1)(x==odd)
再定义
p
a
t
h
(
x
)
path(x)
path(x)表示从
x
x
x开始,一直到1的路径上,所有出现的数,例:
path(1)={1},path(15)={15,14,7,6,3,2,1}
给出
n
,
k
≤
1
e
18
n,k\leq 1e18
n,k≤1e18,要求求出最大的数,在所有的path(x)
(
1
≤
x
≤
n
)
(1\leq x \leq n)
(1≤x≤n)中,其出现的次数大于等于k。
大概就是对于奇数,偶数分别二分,然后求最大的答案.
关键在于求一个数x被覆盖了多少次,这个可以变成以x为前缀的数,比n小的有多少个,然后简单计数一下,就可以发现对奇偶分别有单调性.
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
char c=getchar();int t=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
return t*f;
}
int n,k;
bool calc(int x){
if(x&1){
int ans=1;//2x+(2-1)
for(int i=2;x*i<=n;i*=2){
int tmp=n-x*i;
if(tmp<i){ans+=tmp+1;break;}
else ans+=i;
}
//printf("%d %d\n",x,ans);
return ans>=k;
}
else{
int ans=0;//2x+2*2-1
for(int i=1;x*i<=n;i*=2){
int tmp=n-x*i;
if(tmp<2*i){ans+=tmp+1;break;}
else ans+=2*i;
}
//printf("%d %d\n",x,ans);
return ans>=k;
}
}
signed main(){
//freopen("5.in","r",stdin);
//freopen("5.out","w",stdout);
n=read(),k=read();
int l=1,r=(n+1)/2,ans1=1;
while(l<=r){
int mid=(l+r)>>1;
if(calc(mid*2-1)){ans1=mid*2-1,l=mid+1;}
else r=mid-1;
}
l=1,r=n/2;int ans2=0;
while(l<=r){
int mid=(l+r)>>1;
if(calc(mid*2)){ans2=mid*2;l=mid+1;}
else r=mid-1;
}
printf("%lld\n",max(ans2,ans1));
return 0;
}