分析:二进制中不含101的数字,就直接用二进制来分析。
假设对于任意一个二进制数字,如果已经满足了不含101的要求,例如下面的数字:
100100000000000000000000000。
如果只要在已有的最后一个1后面再添加一个1,满足不含101的要求。
可以用下面的代码实现。
int num = 0b1001000000000000000000000000;
int zero_num = 26; //如果最后有26个连续的0
int ok_num;
for (int i = zero_num - 1; i >=0; i--) {
if ( zero_num - i == 2) continue;
//每个ok_num都是一个不含101的数字。
//然后又可以将生成的ok_num作为一个新的基础数字,生成新的不含101的数字。
//用递归的方法将其作为参数进行新的计算,同时将zero_num做一个调整传递下去
ok_num = num + 1 << i;
}
对于int类型,所有的数字都是32位的,遍历一个区域中所有不含101的数字将是一个很简单的方法。
#include <stdio.h>
#include <stdlib.h>
/*
* 将每个数字当作是一个32位的二级制数字,从最高32位开始遍历,不符合要求的不做+1.
*/
unsigned int count = 0;
/*
*参数说明
*value 当前遍历到的数字大小
*id 当前遍历到的二进制位数
*alarm 上一个函数传递过来的 id - i,如果=2,则认为碰到了101
*min 题目中规定的最小数字
*max 题目中规定的最大数字
*/
void cacu(unsigned int value, int id, int alarm,
unsigned int min, unsigned int max) {
if(value > max) return;
if(value * 2 < min && value != 0) return;
//alarm等于二,相当于碰到101.
//如100010000000后面离最后一个1的距离为2,会变成10010100000,
//不符合要求,不需要进入后面的计算
if(alarm == 2) return;
//这个循环是和上面代码寻找符合的数字,为了优化算法,
//将判断放到下一个递归中,否则每循环一次,判断一次
for(int i = id - 1; i >= 0; i--) {
cacu(value + (1 << i), i, id - i, min,max);
}
if (value < min) return;
count++; //传进来的二数字如果符合要求,则+1
return;
}
int main(void) {
unsigned int min;
unsigned int max;
scanf("%ud",&min);
getchar();
scanf("%ud",&max);
cacu(0, 32, 0, min, max); //每个数字都认为是一个32位的二进制数字
printf("%u\n",count);
}