描述
二进制是计算机学科中广泛应用的一种数制, 用0和1两个数码来表示数字, 进位规则为"逢二进一"
用2整除十进制整数, 可以得到一个商和余数, 再用2去除商, 又会得到一个商和余数, 如此进行, 直到商为小于1时为止, 然后把先得到的余数作为二进制的低位有效位, 后得到的余数作为二进制的高位有效位, 依次排列起来
以13举例, 十进制13 = 二进制1101
13 ÷ 2 = 6 ...... 1
6 ÷ 2 = 3 ...... 0
3 ÷ 2 = 1 ...... 1
1 ÷ 2 = 0 ...... 1
给你两个正整数L和R, 那么从大于等于L到小于等于R的所有正整数中, 二进制中数码"1"出现的次数最多的是哪个数? 如果有多个整数满足条件, 那么你需要输出其中最小的整数
格式
输入格式
输入仅包含2个正整数L和R (1≤L≤R≤), 由一个空格隔开, 含义如题面所述
输出格式
输出一个正整数, 含义如题面所述
样例
输入样例
8 14
输出样例
11
限制
时间限制: 1000 ms
内存限制: 65536 KB
暴力,找点规律,强制从l——>r 一定会超时
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int lborder[1000];
int rborder[1000];
void calcl(ll i) {
ll j = 0;
while (i) {
lborder[j] = i % 2;
i /= 2;
j++;
}
}
void calcr(ll i) {
ll j = 0;
while (i) {
rborder[j] = i % 2;
i /= 2;
j++;
}
}
int main() {
ios::sync_with_stdio(false);
ll l, r, res = 1;
int cnt = 0;
cin >> l >> r;
while (r > res) {
res = res * 2 + 1;
cnt++; //用cnt来初步判断一个cnt,cnt即目前判断的最多1的可能
} //例如l:8 r:14 14<15 最多3个1
calcl(l); calcr(r); //将l,和r转成二进制来进行处理
res = 0;
if (l == 1 && r == 1) { //将特例直接处理
res = 1;
}
else {
for (int i = 0; i < cnt; i++) //将之前判断的1的数量的值给res,并且最多1的最小值
res += pow(2, i);
while (res < l) {
res += pow(2, cnt); //如果不满足左边界,进行右移,从数值影响最小的开移,保持尽量小
res -= pow(2, cnt - 1);
cnt--;
}
}
//下面是结果不是判断的 cnt 个1的求解,
int maxlen; //time limit warning 注意处理,处理不好有超时风险
if (l == 1 && r == 1) {
res = 1;
}
else if (res > r) {
cnt++;
ll tmp = l;
res = tmp;
int p = 0;
while (tmp < r && p <= cnt) { //根据之前得到的左边界二进制做判断,一位一位去加
if (lborder[p] != 1 && p <= cnt && tmp + pow(2, p) <= r) {
tmp += pow(2, p);
res = tmp;
}
p++;
}
}
cout << res;
return 0;
}