当前位置: 首页 > news >正文

luoguP8764 [蓝桥杯 2021 国 BC] 二进制问题

luogu题目传送门

题目描述

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

输入格式

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

输出格式

输出一个整数表示答案。

输入输出样例

输入 #1

7 2

输出 #1

3

说明/提示

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

对于 60% 的评测用例, 1\leq N \leq 2*10^{9},1≤K≤30 。

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

蓝桥杯 2021 国赛 B 组 H 题(C 组 J 题)。

思路

像这样时间复杂度O(N)都要超的题目显然是数位dp,只是将原来的十进制改为二进制就可以了

对于深搜的第二个参数,我们只需要定义一个sum,记录已经选了几个 1 

最后退出时如果 sum 不为 k 就返回 0,否则返回 1

Code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
ll f[205][205][2],a[205],k;
ll dfs(ll pos,ll sum,ll lim){
	if(pos==0){
		if(sum==k)return 1;//sum==k 才满足条件 
		return 0;
	}
	if(f[pos][sum][lim]!=-1)return f[pos][sum][lim];//如果有了就直接返回 
	ll ans=0;
	ll en=(lim?a[pos]:1);//小细节:二进制最大为 1 ,不要打成 9 
	for(ll i=0;i<=en;i++){
		ans+=dfs(pos-1,sum+(i==1),lim&&i==en);
	}
	return f[pos][sum][lim]=ans;
}
ll solve(ll x){
	ll o=0;
	memset(f,-1,sizeof(f));
	memset(a,0,sizeof(a));
	while(x>0){//将 x 转为二进制 
		a[++o]=x%2;
		x/=2;
	}
	return dfs(o,0,1);
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	ll r;
	cin>>r>>k;
	cout<<(solve(r)-solve(0));
	return 0;
}

相关文章:

  • 嵌入式开发应该具备哪些编程思维?
  • JDK1.8新特性面试题
  • springboot整合redis
  • 随机生成多孔介质matlab程序
  • 【kafka系列】生产者
  • 第十二篇:黑客帝国终章——电子技术思维导图与三电技术进化论
  • 线程安全的集合类
  • 每日十题八股-补充材料-2025年2月15日
  • Bob the Canadian
  • 安装Homebrew时提示Warning: /opt/homebrew/bin is not in your PATH.
  • UNET改进62:添加HFERB模块|提取高频信息的高频增强残差块
  • 基于Deepseek自动生成单元测试的Idea插件
  • 5分钟掌握LM Studio本地部署DeepSeek R1
  • Rust包管理
  • 计算机软件毕业设计选题指南:热门方向与创新思路
  • 【java】方法的值传递
  • 数据守护者:备份文件的重要性及自动化备份实践
  • 《深度Q网络优化:突破高维连续状态空间的束缚》
  • 代码随想录算法营Day39 | 416. 分割等和子集
  • 小火车理论
  • 蔡建忠已任昆山市副市长、市公安局局长
  • 韶关一企业将消防安装工程肢解发包,广东住建厅:罚款逾五万
  • 中国首艘海洋级智能科考船“同济”号试航成功,可搭载水下遥控机器人
  • 广西等地旱情缓解,水利部针对甘肃启动干旱防御Ⅳ级响应
  • 董军在第六届联合国维和部长级会议上作大会发言
  • 上海黄浦江挡潮闸工程建设指挥部成立,组成人员名单公布