蓝桥杯第1593题——二进制问题

2024-04-02 19:20
文章标签 问题 蓝桥 二进制 1593

本文主要是介绍蓝桥杯第1593题——二进制问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

小蓝最近在学习二进制。他想知道 1 到 N 中有多少个数满足其二进制表示中恰好有 K 个 1。你能帮助他吗?

输入描述

输入一行包含两个整数 N 和 K。

输出描述

输出一个整数表示答案。

输入输出样例

示例

输入

7 2

输出

3

评测用例规模与约定

对于 30% 的评测用例,1 ≤ N ≤ 10^6,1 ≤ K ≤ 10。

对于 60% 的评测用例,1 ≤ N ≤ 2×10^9,1 ≤ K ≤ 30。

对于所有评测用例,1 ≤ N ≤ 10^18,1 ≤ K ≤ 50。

解题思路

这道题大致的问题就是给定一排位置,填或者不填的问题,我们可以考虑使用数位dp的思想。

对于n个位置填k个1的方案数量是典型的排列组合,虽然K的值最高只有50,计算排列组合C_{m}^{n}也是可以实现的,但这里我们综合考虑使用帕斯卡公式,即C_{n}^{m} = C_{n-1}^{m} + C_{n-1}^{m-1}

于是我们可以定义dp[i][j]:在长度为 i 的二进制序列中填 j 个 1 的组合数。

帕斯卡公式的证明就是这道题的原理,即n个数中取m个元素的组合数——包含第一个数不取,在剩下的n-1个数中取m个数;和第一个数取,在剩下n-1个数中取m-1个数的总和。

题目要求统计包含K个1的二进制数的数量,以N的二进制为1011,取k=3为例,我们可以将1011分解为以下几个区间考虑:0000~0111、1000~1001、1010~1010、1011。

这样分的理由是,第一个数不填1,考虑剩下3个位置填3个1的方法总数,这不就正好是在000~111这个长度为3的二进制序列中填3个1的排列总数吗,即dp[3][3]。

那么比111更大的数即代表着第一个数一定填1,在第二个区间中,我们是在第一个数填1的情况下,考虑第三个数不填1的排列数,即剩下1个位置填2个1满足要求——dp[1][2]。

第三个区间考虑在第一个位置和第三个位置都填1的情况下,第四个位置不填1的情况,那么就要加上在剩下0个位置填1个1的组合数——dp[0][1]。

最后还剩一个单独的1011,其目的是要留着特判,因为我们前面一直都是在遇到1的情况下考虑这个位置不填1有多少种满足要求的可能性,那么我们就会漏掉最后一个位置填1的情况没有计算,在最后一个位置填1,并且刚好满足k个1的时候,就需要增加一种组合数。

根据上述逻辑,此数据的答案即为:dp[3][3] + dp[1][2] + dp[0][1] + 1  =  1 + 0 + 0 + 1  =  2种

import java.util.*;
import java.io.*;public class Main {static long n;static int k;static long[][] dp;public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextLong();k = sc.nextInt();init();System.out.println(solve(n));}public static long solve(long n) {char[] s = Long.toBinaryString(n).toCharArray();long ans = 0;// ones 用于记录已经填的1的数量int ones = 0;for (int i = 0; i < s.length; i++) {int po = s.length - i;if (s[i] == '1') {// 先考虑位置po不填1的可能性ans += dp[po - 1][k - ones];// 然后填上一个1并记录ones++;// 由于在ones等于k的时候还有一次后续什么都不填的可能性,即dp[xxx][0] = 1// 所以只在填超了以后才breakif (ones > k) {break;}}// 如果最后一位刚好填够k个1,会漏计算1种情况,需要补上if (po == 1 && ones == k) {ans++;}}return ans;}public static void init() {dp = new long[65][65];dp[0][0] = 1;for (int i = 1; i < 65; i++) {for (int j = 0; j <= i; j++) {if (j == 0) {dp[i][j] = 1;} else {dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];}}}}
}

这篇关于蓝桥杯第1593题——二进制问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/870841

相关文章

SpringBoot项目jar依赖问题报错解析

《SpringBoot项目jar依赖问题报错解析》本文主要介绍了SpringBoot项目中常见的依赖错误类型、报错内容及解决方法,依赖冲突包括类找不到、方法找不到、类型转换异常等,本文给大家介绍的非常... 目录常见依赖错误类型及报错内容1. 依赖冲突类错误(1) ClassNotFoundExceptio

MybatisPlus 多数据源切换@DS注解失效问题解决

《MybatisPlus多数据源切换@DS注解失效问题解决》在业务开发中使用到了多数据源,遇到了@DS注解失效问题,有两个场景使用到同一个@DS的查询方法,下面就来介绍一下该问题的解决,感兴趣的可以... 在业务开发中使用到了多数据源,遇到了@DS注解失效问题,有两个场景使用到同一个@DS的查询方法,一个正

Centos7 firewall和docker冲突问题及解决过程

《Centos7firewall和docker冲突问题及解决过程》本文描述了一个在CentOS7上使用firewalld和Docker容器的问题,当firewalld启动或重启时,会从iptable... 目录系统环境问题描述问题排查解决办法总结本文只是我对问题的记录,只能用作参考,不能China编程说明问题,请

Python在二进制文件中进行数据搜索的实战指南

《Python在二进制文件中进行数据搜索的实战指南》在二进制文件中搜索特定数据是编程中常见的任务,尤其在日志分析、程序调试和二进制数据处理中尤为重要,下面我们就来看看如何使用Python实现这一功能吧... 目录简介1. 二进制文件搜索概述2. python二进制模式文件读取(rb)2.1 二进制模式与文本

JAVA Calendar设置上个月时,日期不存在或错误提示问题及解决

《JAVACalendar设置上个月时,日期不存在或错误提示问题及解决》在使用Java的Calendar类设置上个月的日期时,如果遇到不存在的日期(如4月31日),默认会自动调整到下个月的相应日期(... 目录Java Calendar设置上个月时,日期不存在或错误提示java进行日期计算时如果出现不存在的

Mybatis对MySQL if 函数的不支持问题解读

《Mybatis对MySQLif函数的不支持问题解读》接手项目后,为了实现多租户功能,引入了Mybatis-plus,发现之前运行正常的SQL语句报错,原因是Mybatis不支持MySQL的if函... 目录MyBATis对mysql if 函数的不支持问题描述经过查询网上搜索资料找到原因解决方案总结Myb

Nginx错误拦截转发 error_page的问题解决

《Nginx错误拦截转发error_page的问题解决》Nginx通过配置错误页面和请求处理机制,可以在请求失败时展示自定义错误页面,提升用户体验,下面就来介绍一下Nginx错误拦截转发error_... 目录1. 准备自定义错误页面2. 配置 Nginx 错误页面基础配置示例:3. 关键配置说明4. 生效

Springboot3统一返回类设计全过程(从问题到实现)

《Springboot3统一返回类设计全过程(从问题到实现)》文章介绍了如何在SpringBoot3中设计一个统一返回类,以实现前后端接口返回格式的一致性,该类包含状态码、描述信息、业务数据和时间戳,... 目录Spring Boot 3 统一返回类设计:从问题到实现一、核心需求:统一返回类要解决什么问题?

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

maven异常Invalid bound statement(not found)的问题解决

《maven异常Invalidboundstatement(notfound)的问题解决》本文详细介绍了Maven项目中常见的Invalidboundstatement异常及其解决方案,文中通过... 目录Maven异常:Invalid bound statement (not found) 详解问题描述可