NYOJ 222 整数中的1 (二进制位运算,找规律)
2016-05-03 22:05
281 查看
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=222
时间限制:3000 ms | 内存限制:1000 KB
难度:4
描述给出两个非负32位整型范围内的数a,b,请输出闭区间[a,b]内所有数二进制中各个位的1的总个数。
输入一行,给出两个整形数a,b(0<=a<=b<=150000000),空格分隔。
输出一行,输出结果
样例输入
样例输出
看起来是位运算,但是会超时。。所以要找一下规律。
对于一个数0到n的n+1个数,二进制第一位每2个数会出现1个1,第二位每4个数会出现2个连续的1,第三位每8个数会出现4个连续的1,第四位每16个数会出现8个连续的1。
这样规律就找到了。不过还要考虑一些特例,如果给的n不能正好被整除,多出的那部分只要超过区间的一半,那么超出的那部分一定也是1,因为每个区间中前一半是0,后一半是1。
对于while的结束条件也要好好考虑。
整数中的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; }
相关文章推荐
- 8数码,欺我太甚!<bfs+康拓展开>
- 我的你的他们的
- Android Studio 进阶详细配置
- 反向工程--Visio 2007自动生成ER图
- CDN基本工作过程
- 面试 -- Static关键字
- Axure的学习
- hdu 5358(尺取法)
- 野指针--内存泄漏--缓存区溢出--栈溢出
- iOS category内部实现原理
- [BZOJ2811][Apio2012]Guard(线段树+贪心+二分)
- 取数字
- 设计模式C++学习笔记之十一(c/c++面试笔试题)
- Contiki在CC2530上的内核移植
- Unity+Vuforia 防抖动解决方案
- 【git】日志更改
- C++11中的POD
- eclipse里的插件问题
- 一个屌丝程序猿的人生(一)
- 设备管理器