Description
给定一个范围[a,b] (0<=a<b<=10^18) 求出该范围内二进制中1的个数最多的数,如果存在多个答案,输出最小的那个数
Input
输入数据有多组,每组数据输入两个整数a,b,表示区间[a, b]。
Output
输出该区间内二进制的1最多的整数,如果有多个数二进制1的个数相同,输出最小的那个数。
Sample Input
4 8 7 14
Sample Output
7 7
思路:
区间[a,b],如果a==b,输出a, 先把a,b化为二进制数,每位分别保存到数组中,如果a的二进制位数小于b的位数,那么直接输出 2^(b的位数-1) -1(此处如果b等于 2^b的位数 -1 就直接输出b) ,也就是二进制数比b少一位且所有位均为1,如果a的位数等于b的位数,要求最小的符合题意的数,尝试着从a的二进制低位开始,如果是0,将其变为1,看是否小于等于b,如果是,继续操作,如果不是,退出。
要注意10^18 <2^62 所以要存这么大是数组才行 2^63超过longlong范围
#include<iostream> #include<cstdio> using namespace std; #define ll long long ll n,m; int nn[65],mm[65]; ll p[65]; void inti() {p[0]=1;for(int i=1;i<63;i++)p[i]=p[i-1]<<1; } int getbit(ll x,int a[]) {int s=0;while(x){a[s++]=x%2;x/=2;}return s; } int main() {inti();while(~scanf("%lld%lld",&n,&m)){int lenn=getbit(n,nn);int lenm=getbit(m,mm);if(lenn<lenm){// input 3 7 output 7if(m==p[lenm]-1)printf("%lld\n",m);else printf("%lld\n",p[lenm-1]-1);continue;}// printf("lenn=%d\n",lenn);for(int i=0;i<lenn;i++){if(nn[i]==0){//printf("** %lld %d\n",n,i);if(n+p[i]<=m)n+=p[i];else break;}}printf("%lld\n",n);}return 0; }