题目
描述
给出两个非负32位整型范围内的数a,b,请输出闭区间[a,b]内所有数二进制中各个位的1的总个数。
输入
一行,给出两个整形数a,b(0<=a<=b<=150000000),空格分隔。
输出
一行,输出结果
样例输入
1 2
样例输出
2
思路
来看0~7的二进制表示
0 1
10 11
100 101 110 111
你发现什么了么?
对于2~3就是在0~1上加上1
对于4~5就是在0~4上加上1
设 y(n) 表示 0∼n 中二进制1个数
那么对于 y(2n−1)−y(2n−1−1)=2n+y(2n−1)−y(2n−2)
那么对于任意一个数来说 y(n)=y(2Max−1)+y(n−(2Max−1))+n−(2Max−1)
Tips:将n分为前 2m−1 个数和后 n−(2m−1) 个数分别计算,而后边的 n−(2m−1) 又等于 0∼n−(2m−1) 前边加上1来计算….如此迭代
代码
//写的比较凌乱 QAQ
#include<stdio.h>
int Num[32];
int GetNum(int N)
{
int i=0;
int Sum=0;
while(N>0)
{
i=0;
while(N>=1<<i)
i++;
i--;
Sum+=Num[i]+N-(1<<i)+1;
N-=1<<i;
}
return Sum;
}
int main()
{
int Sum=0;
for(int i=1;i<32;i++)
{
Sum+=Num[i-1];
Num[i]+=Sum+(1<<(i-1));
}
for(int i=1;i<32;i++)
Num[i]+=Num[i-1];
int A,B;
scanf("%d %d",&A,&B);
printf("%d\n",GetNum(B)-GetNum(A-1));
return 0;
}