华为od考试,不含101(二进制中的101)的数字

分析:二进制中不含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);
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值