codeforces 1271E

题意

定义一个函数 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(x1)(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,k1e18,要求求出最大的数,在所有的path(x) ( 1 ≤ x ≤ n ) (1\leq x \leq n) 1xn中,其出现的次数大于等于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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值