【2025刷题笔记】- 不含101的数

刷题笔记合集🔗

不含101的数

问题描述

小柯在学习二进制时,发现了一类不含 101 的数,也就是:

将数字用二进制表示,不能出现 101 。
现在给定一个整数区间 ,请问这个区间包含了多少个不含 101 的数?

输入格式

输入的唯一一行包含两个正整数 )。

输出格式

输出的唯一一行包含一个整数,表示在 区间内一共有几个不含 101 的数。

样例输入

1 10
10 20

样例输出

8
7
样例 解释说明
样例1 区间 内, 的二进制表示为 的二进制表示为 ,因此区间 内有 个不含 101 的数。
样例2 区间 内,满足条件的数字有 因此答案为

数据范围

题解

这道题要求我们统计整数区间 中有多少个二进制表示不含 "101" 的数字。

思路分析

最直接的方法是遍历区间内的每个数,将其转换为二进制形式,然后检查是否包含 "101"。但由于题目给出的区间范围可能非常大(最大可达 ),这种暴力枚举方法会超时。

这类问题可以采用数位DP(数字动态规划)的方法解决。数位DP适合解决与数字的二进制/十进制表示相关的计数问题。

数位DP解法

我们定义状态: 表示当前处理到二进制的第 位,前一位数字是 ,前前一位数字是 时,可能的数字个数。

关键思路:

  1. 从高位到低位依次处理二进制位
  2. 记录当前处理到的位置前两位的值,判断是否会形成 "101"
  3. 对于每一位,尝试填充0或1,但不能导致出现 "101" 序列
  4. 处理边界情况:不能超过原数值的限制

数位DP中的一个关键优化是记忆化,这样我们不会重复计算相同状态。

时间复杂度分析

数位DP的时间复杂度与数字的二进制位数相关。一个 级别的数字,其二进制位数约为

时间复杂度:,即二进制位数 × 前一位可能值 × 前前一位可能值。 空间复杂度:

在这个问题中,时间复杂度实际上是 ,是常数级别的,因此可以很快得到结果。

参考代码

  • Python
import sys
input = lambda:sys.stdin.readline().strip()

# 通过数位DP计算不包含101的数字个数
def cnt(num):
    # 将数字转为二进制并转为list
    bin_lst = list(bin(num)[2:])
    digs = [int(x) for x in bin_lst]
    n = len(digs)
    
    # 初始化记忆化数组,f[i][j][k]表示考虑前i位,前一位为j,前前一位为k时的合法数字个数
    f = [[[-1 for _ in range(2)] for _ in range(2)] for _ in range(n)]
    
    # dfs函数用于计算合法数字个数
    def dfs(pos, pre, ppre, lim):
        # 已处理完所有位,得到一个合法数字
        if pos == n:
            return 1
            
        # 如果不受上限限制且已经计算过,直接返回结果
        if not lim and f[pos][pre][ppre] != -1:
            return f[pos][pre][ppre]
        
        # 确定当前位可以填的上限
        up = digs[pos] if lim else 1
        ans = 0
        
        # 尝试填0或1
        for d in range(up + 1):
            # 如果填1且前两位是1和0,形成101,则跳过
            if d == 1 and pre == 0 and ppre == 1:
                continue
            # 递归计算下一位
            ans += dfs(pos + 1, d, pre, lim and d == up)
            
        # 记忆化存储
        if not lim:
            f[pos][pre][ppre] = ans
            
        return ans
    
    # 初始时没有前两位,用0表示
    return dfs(0, 0, 0, True)

# 主函数
l, r = map(int, input().split())
# 计算[1,r]中的合法数字个数,减去[1,l-1]中的合法数字个数
print(cnt(r) - cnt(l-1))
  • Cpp
#include <bits/stdc++.h>
using namespace std;

// 计算[1,n

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

算法刷题笔记 文章被收录于专栏

本专栏收集并整理了一些刷题笔记

全部评论

相关推荐

Xcccc25:b站这个笔试是真出生,两个意愿笔试全满分都过不了
投递哔哩哔哩等公司10个岗位
点赞 评论 收藏
分享
1.算法&nbsp;合并链表还有个也是链表的top100忘记了2.自我介绍3.消息队列为了解决什么问题异步秒杀具体是一个怎么样的实现消费的时候发现没有库存怎么办为什么引入redis能不能在启动的时候把所有的信息都加载到服务内存而不用redis用过rabbitmq延时消费吗4.沾包问题根本原因ip层会沾包吗http会吗5.http常用的头字段6.websocket建立的过程和http的关系7.jwt和session后端服务有多个session怎么处理8.反问其实在正式开始找工作之前,从选择做java后端这个方向开始我就时不时会后悔,虽然当初看着java岗位多进来了,但是实际上看这几年的招聘情况是不甚乐观,也曾经想过要不要转前端或者go,但是因为自己的惰性和沉没成本没能狠下心去转。在这学期国庆终于把最基础的课程项目和简历做完之后就开始投了。说实话和我想象的完全不一样,我想着就是先投小厂实习一段时间再中厂,等暑期实习冲击大厂,可以就业形势远比我想象的要紧张,中小厂完全不回我简历或者是没有除了应届生以外的实习渠道,反而是那几家中大厂至少还能投(虽然大部分也是泡池子),这也就彻底改变了我的规划,决定all&nbsp;in中大厂,正如9本和普通本科的面试/投递率有千差万别,我相信有一段中大厂实习的背书肯定不会发生别人口中那种暑期实习泡池子的情况。在写下这期笔记的时候我也已经有自己的去处了,可能还会更新几个面经,但是说实话大头就要放在实际工作和准备暑期实习上了。腾讯,我们暑期实习见!
查看18道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务