二进制表示法中1的个数最多的整数 构造

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;
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值