问题 F: 神殿
题目描述
icebound通过勤工俭学,攒了一小笔钱,于是他决定出国旅游。这天,icebound走进了一个神秘的神殿。神殿由八位守护者守卫,总共由64个门组成,每一道门后都有一个迷宫,迷宫的大小均为100 × 100。icebound在迷宫中总共耗时T小时,消耗食物K公斤。历经千辛万苦之后,icebound终于穿越了迷宫,到达了神殿的中心。神殿的中心有一个宝箱。宝箱上显示有两个正整数l和r。icebound苦思冥想,终于发现一些打开宝箱的线索。你需要找到一个数P,它具有一个美妙的性质:它是[l, r]中所有数的二进制表示里,1的个数最多的一个数。如果你发现了这个美妙的数字,你就可以打开宝箱,获得巨额财富。
比如[4, 8]中:
4: 0100
5: 0101
6: 0110
7: 0111
8: 1000
二进制表示中1的个数最多的数是7,它含有3个1。
输入
输入一行,两个正整数:l和r,用空格隔开,代表神殿中宝箱上显示的数。
1 ≤ T < 231,1 ≤ K ≤ 105,1 ≤ l ≤ r ≤ 2 × 109
输出
一个十进制数P,代表满足条件的解。如果有多个P满足条件,输出最小的P。
样例输入 Copy
4 8
样例输出 Copy
7
题意:找出L 到 R这个区间内的数的二进制表示形式下 1 的个数最多的数。
思路:先把 L 和 R 表示成二进制,求出二进制表示形式下的长度l1,l2,R全都是1或者L=R,直接输出R,如果l1<l2, 退而求其次,让l2-1, 这就是1的个数,转换成十进制输出即可,如果长度相同,则从高位开始比较,如果出现不同的,让l1不同位后面的全部为1 即可,转换成二进制输出,代码如下:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#define LL long long
#define inf 0x3f3f3f3f
#include<algorithm>
using namespace std;
int a[50],b[50];
int solve(int c[],LL x)
{
int i=0;
while(x)
{
c[i++]=(int)(x%2);
x=x/2;
}
return i;
}
int main()
{
int l,r;
cin>>l>>r;
int l1=solve(a,l);
int l2=solve(b,r);
if(l==r)
{
printf("%l0ld\n",l);
return 0;
}
int flag=0;
for(int i=0; i<l2; i++) //倒着来
{
if(!b[i])
{
flag=1;
break;
}
}
if(!flag)
{
printf("%lld\n",r);
return 0;
}
LL x=0;
if(l1==l2)
{
for(int i=l1-1; i>=0; i--)
{
if(a[i]<b[i]) //0 1
{
x=x*2;
for(int j=i-1; j>=0; j--)
x=x*2+1;
break;
}
else x=x*2+a[i]; //1 0
}
}
else
{
for(int i=1; i<l2; i++) //退而求其次
x=x*2+1;
}
printf("%lld\n",x);
return 0;
}