原题如
Description
问区间[x,y]中有多少数的二进制表示是ABAB..AB型或者A型的,其中A是n个1,B是m个0,n, m > 0
Input
两个整数x和y(0<=x,y < 2^63)
Output
输出[x,y]中有多少满足条件的数
Sample Input
1 10
Sample Output
10
思路:先构建模板,像110, 1110, 或全是1等等,把所有的满足要求的数求出来存在一个vector里,然后总共满足的数才四千多,所以之后进行枚举看有多少满足要求的数在指定区间即可。
代码中有思路,
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const unsigned LL inf = pow(2, 63);
vector<LL> vt; //用vector存满足要求的数,不需要用set,无重
vector<LL>::iterator it;
void add(int i, int j){
LL k = 1, ans = 0, x, p;
int c = 63/(i+j), a, b, flag = 1;
while(c--){ //假如模板是110,那么110110也是可以的,这样用c可以表示63位内可以用这个模板的数的个数
if(flag) a = j-1, flag = 0;//由于k初值为1表示2^0,消耗了一次0,所以第一次0的个数减1,不明白模拟一遍便知
else a = j;
b = i;
while(a--) k *= 2;
while(b--){
k *= 2;
ans += k;
}
vt.push_back(ans); //得到的ans形如110,110110,110110110
x = 1, p = 1;
for(int l = 1; l < i; ++l){
x *= 2;
p += x;
}
LL op = (ans<<i) + p;
if(op >= 0) //判断数是否超long long范围,超范围的数会变为绝对值很大的负数
vt.push_back(op); //(ans<<i)+p形如11011, 11011011
}
}
void init(){
for(int i = 1; i <= 63; ++i)
for(int j = 1; j <= 63-i; ++j)
add(i, j); //i,j模拟模板的1个数和0个数
LL k = 1, x = 1;
vt.push_back(1); //把全是1的情况也加进去
for(int i = 1; i < 63; ++i){
k *= 2;
x += k;
vt.push_back(x);
}
}
int main(){
LL a, b, ans = 0;
init();
cin >> a >> b;
for(it = vt.begin(); it != vt.end(); ++it){ //遍历一次求在这个范围的满足要求数的个数
if(*it >= a && *it <= b) ++ans;
}
// cout << inf << endl;
// cout << vt.size() << endl;
cout << ans << endl;
return 0;
}