题目链接:http://codeforces.com/problemset/problem/768/B点击打开链接
先将该数用二进制表示 1010
观察序列 发现二进制中的第一位的1位于1 3 5 7 9 11 13 15的位置
第二位的0位于2 6 10 14
第三位的1位于4 12
第四位的0位于8
将1010这个二进制数的每一位附上权值 每一位对应为1 2 4 8 从左到右位置为 0 1 2 3 (其实就是2的次方对应关系)
于是可以发现 对于序列中任意一个位置的值 都具有以下规律
设当前位置为position
position的值对应于 position的因子中最大的2的N次方数 即为该数二进制的第N位的值
有点难懂 还是举10的例子
对于序列的第3位 他的因子中最大的2的N次方数为1 即N=0 所以为二进制1010的第0位 也就是第一个1
对于序列的第6位 她的因子中最大的2的N次方数为2 即N=1 所以对应1010的第一个0
。。。。。。12。。。。。。。。。。。。。。。4 即N=2 所以对应第三位 也就是第二个1
找出规律之后 代码就很简单了
因为范围不大 因此枚举他需要的区间的每个位置 根据规律计算当前的数是不是1
#include <iostream>
#include <stdio.h>
#include <limits.h>
#include <stack>
#include <algorithm>
#include <queue>
#include <string.h>
#include <set>
using namespace std;
vector<long long int > s;
int main()
{
long long int n,l,r;
cin >> n >> l >> r;
while(n!=0)
{
s.push_back(n%2);
n/=2;
}
long long int cnt=0;
reverse(s.begin(),s.end());
s.push_back(0);
for(long long int i=l;i<=r;i++)
{
long long int j=0;
long long int mid=i;
while(mid%2==0)
j++,mid/=2;
if(s[j]==1)
cnt++;
}
cout << cnt;
}