NYOJ 222 整数中的1 (二进制位运算,找规律)

本文介绍了一种高效计算指定整数区间内所有数二进制表示中1的总数的方法。通过分析位运算规律,避免了直接遍历计算带来的性能问题。文中提供了一个C++实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=222

整数中的1

时间限制: 3000 ms  |  内存限制: 1000 KB
难度: 4
描述
给出两个非负32位整型范围内的数a,b,请输出闭区间[a,b]内所有数二进制中各个位的1的总个数。
输入
一行,给出两个整形数a,b(0<=a<=b<=150000000),空格分隔。
输出
一行,输出结果
样例输入
1 2
样例输出
2

看起来是位运算,但是会超时。。所以要找一下规律。

对于一个数0到n的n+1个数,二进制第一位每2个数会出现1个1,第二位每4个数会出现2个连续的1,第三位每8个数会出现4个连续的1,第四位每16个数会出现8个连续的1。

这样规律就找到了。不过还要考虑一些特例,如果给的n不能正好被整除,多出的那部分只要超过区间的一半,那么超出的那部分一定也是1,因为每个区间中前一半是0,后一半是1。

对于while的结束条件也要好好考虑。

#include <iostream>
#include <cstdio>
using namespace std;
int getnum(int x) {
	if(x <= 0) return 0;
	int y = x + 1;   //因为该规律是从0000开始算起的,相当于一共有x+1个数 
	int q = 2, p = 1, sum = 0;  //每连续q个数出现p个连续的1 
	while(y >= q / 2) {		//位数不够才退出 
		sum += y / q * p;  //加整位 
		if(y % q > q / 2) sum += y % q - q / 2;  //不完整的需要判断是否大于区间的一半,因为每个区间前半部分是0,后半部分是1 
		q *= 2;
		p *= 2;
	}
	return sum;
}
int main() {
	int n, m;
	scanf("%d %d", &n, &m);
	printf("%d\n", getnum(m) - getnum(n - 1));
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值