1的个数最多的整数
给定整数a和b(0≤a≤b≤263-1),输出区间[a,b]中对应二进制表示含1的个数最多的整数,如果存在多个解,则输出符合条件的最小的整数。
输入格式:
第1行:一个整数T(1≤T≤10000)为问题数。
第2~T+1行:每个问题占一行,每行输入两个整数a和b(0≤a≤b≤263-1)。数据之间用一个空格分隔。
输出格式:
对于每个问题,输出一行问题的编号(0开始编号,格式:case #0: 等)。然后对应每个问题在一行中输出结果。
Sample Input
3
0 14
100 1000
39668697550916990934597827455649079876
Sample Output
case#0:
7
case#1:
511
case#2:
4035225266123964415
Hints:
第一个样例数据:a=0,b=14,在[0,14]之间含1最多的整数为7(0111),11(1011),13(1101),14(1110),输出最小的整数为7.
假设有两个数(二进制表示)为
110110(较大数)
110010(较小数)
我们从最高位开始逐位比较,记录第一个不同的数字的位置pos,这里是第4个数字不同。
那么输出的答案就是 较大数字的第 1 位到第 pos - 1 位 + 0 + 1111......(后面全部都是1)
也就是 110 0 11
注意:如果较大数字从 pos 位往后全是 1 的话,答案就直接是较大数字。也就是下面这种情况:
110111(较大数)
110010(较小数)
答案11
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX_N 100
using namespace std;
typedef long long int ll;
void ChangeToBinary(ll x, int a[MAX_N])
{
int k = 0;
while (x)
{
a[k++] = x % 2;
x /= 2;
}
}
ll ChangeToNum(int a[MAX_N])
{
ll ret = 0;
for (int i = 0; i < 64; i++)
ret += a[i] * (ll)(pow(2, i) + 0.5);
return ret;
}
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T, Case = 0;
cin >> T;
while (T--)
{
ll a, b;
int aa[MAX_N] = {0}, bb[MAX_N] = {0};
scanf("%lld%lld", &a, &b);
if (a > b)
swap(a, b);
ChangeToBinary(a, aa);
ChangeToBinary(b, bb);
int i = 63;
while (bb[i] == aa[i])
i--;
int flag = 1;
for (int j = i; j >= 0; j--)
{
if (!bb[j])
{
flag = 0;
break;
}
}
if (!flag)
{
bb[i] = 0;
for (int j = i - 1; j >= 0; j--)
bb[j] = 1;
}
printf("case #%d:\n%lld\n", Case++, ChangeToNum(bb));
}
return 0;
}