3303. 1 的个数最多的整数

单点时限: 2.0 sec

内存限制: 256 MB

给定整数 a 和 b,输出区间 [a,b] 中对应二进制表示含 1 的个数最多的整数。

如果存在多个解,则输出符合条件的最小的整数。

输入格式
第一行一个整数 T (1≤T≤104),表示问题数。

接下来 T 行,每行两个整数 a,b (0≤a≤b≤2^63−1)。数据之间用一个空格分隔。

共有两组数据,分别为小数据和大数据,大数据范围如上。对于小数据:T≤10,a≤b≤5⋅106。

输出格式
对于每个问题,输出一行 Case x: y,其中 x 是问题编号,从 1 开始,y 是答案。

样例
input
3
0 14
100 1000
3966869755091699093 4597827455649079876
output
Case 1: 7
Case 2: 511
Case 3: 4035225266123964415
提示
第一个样例数据:a=0,b=14,在 [0,14] 之间含 1 最多的整数为 7(0111),11(1011),13(1101),14(1110),输出最小的整数为 7。

注意,第三组样例不会出现在小数据中。
思路:暴力只能AC一半
如果某数字num低位有0, 可以通过让num和num+1做或运算,将最低位变成1。这种方法不需要将ans显式地转为二进制。注意相关变量保险起见要声明为unsigned long long,原因是a,b可以取到2^63−1,在a基础上运算可能导致数值越界。
思想同上,只是用bitset类来存放二进制数,用weight数组存每个二进制位对应的十进制数,从低到高扫描bitset,出现0时,不使用位运算而是对a直接累加上十进制数。注意变量也要声明为unsigned long long,因为weight[64] = 2^64 > (2^63−1)

#include<iostream>
#include<bitset>
#include<cmath>
#define ull unsigned long long
using namespace std;
ull add(ull a, ull b) {
	ull ans = a;
	while ( (ans|(ans+1)) <= b ) //从低到高,尝试让低位0变成1
		ans |= (ans+1);
	return ans;
}
ull fun(ull a,ull b) {
	ull weight[64]; //每个二进制位对应的十进制数,必须是unsigned LL, 因为2^64 > 2^63-1
	weight[0] = 1;
	for (int i = 1; i < 64; ++i)
		weight[i] = weight[i-1] * 2;
	bitset<64> bit(a);
	ull ans=a;
	for(int i = 0; i < 64; i++) {
		if(bit[i]==0) {
			if(ans+weight[i]<=b) {
				ans+=weight[i];
			} else
				return ans;
		}
	}
}
int main() {
	int n;
	cin>>n;
	for(int i = 0; i < n; i++) {
		ull a,b;
		scanf("%llu%llu",&a,&b);
		printf("Case %d: %llu\n",i+1,fun(a,b));
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值