您的位置:首页 > 其它

Codefroces 485C Bits【贪心+思维】好题

2016-09-29 21:11 246 查看
C. Bits

time limit per test
1 second

memory limit per test
256 megabytes

input
standard input

output
standard output

Let's denote as

the number of bits set ('1' bits) in the binary representation
of the non-negative integer x.

You are given multiple queries consisting of pairs of integers
l and r. For each query, find the
x, such that l ≤ x ≤ r, and


is maximum possible. If there are multiple such numbers find the smallest of
them.

Input
The first line contains integer n — the number of queries (1 ≤ n ≤ 10000).

Each of the following n lines contain two integers
li, ri — the arguments for the corresponding query (0 ≤ li ≤ ri ≤ 1018).

Output
For each query print the answer in a separate line.

Examples

Input
3
1 2
2 4
1 10


Output
1
3
7


Note
The binary representations of numbers from 1 to 10 are listed below:

110 = 12

210 = 102

310 = 112

410 = 1002

510 = 1012

610 = 1102

710 = 1112

810 = 10002

910 = 10012

1010 = 10102

题目大意;

有n个询问,每次询问输入两个数l,r,让你找一个数在【l,r】区间内,使其二进制数中1的个数最多。如果个数相同情况下,输出小的数。比如5和3:101 011,1的个数相同,但是优先输出3.

思路:

1、因为我们要找的解是区间【l,r】内二进制数中1的个数最多的那个数,所以我们贪心的点一定是在1的个数上边。

2、假设数字l的二进制数表达式中,如果有0的存在,那么我们肯定优先将这些0补成1。比如:

8的二进制数为:1000,我们肯定不是优先在当前数上添加位数而是先补上对应位置的0.而且因为填上越靠近末尾的0.花费越少,所以我们从末尾开始补0,如果当这个0补上1,而且补上的数还小于等于r,那么我们这个1就是可以补上的,然后继续判断下一位(对应补最末尾的数需要1,接下来需要2,接下来需要4...............)。

3、那么如果我们按照上述过程补0之后,再考虑增加二进制数长度的问题。而且在增加长度的同时,一定是要添加1的,而不是添加0.因为添加0毫无意义。

假如有这样一个数:

5的二进制数位:101,此时r=30,那么我们首先按照第一步将l的二进制数中的0补成1:

5------------->7 二进制数:111.此时我们再考虑增加其长度:

7------------>15 二进制数:1111,此时我们再考虑增加一个长度:

7------------->31 二进制数:11111,但是此时31 > 30,当前数不在【l,r】区间内,那么其解就是:15(1111);

Ac代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
#define ll __int64
int num[25];
int getnum(ll x)
{
int cont=0;
while(x)
{
num[cont++]=x%2;
x/=2;
}
return cont;
for(int i=0;i<cont;i++)
{
printf("%d",num[i]);
}
printf("\n");
}
int main()
{
int n;
while(~scanf("%d",&n))
{
while(n--)
{
ll l,r;
scanf("%I64d%I64d",&l,&r);
int len=getnum(l);
ll ans=l;
for(int i=0;i<len;i++)
{
if(num[i]==0)
{
ll tmp=(ll)(pow(2,i));
if(ans+tmp<=r)
ans+=tmp;
}
}
for(int i=len;;i++)
{
ll tmp=(ll)(pow(2,i));
if(ans+tmp<=r)
ans+=tmp;
else break;
}
printf("%I64d\n",ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Codefroces 485C