【找规律】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) B. Code For 1

时间:2023-01-25 22:21:10

观察一下,将整个过程写出来,会发现形成一棵满二叉树,每一层要么全是0,要么全是1。

输出的顺序是其中序遍历。

每一层的序号形成等差数列,就计算一下就可以出来每一层覆盖到的区间的左右端点。

复杂度O(log(n))。

#include<cstdio>
using namespace std;
typedef long long ll;
ll n,l,r;
bool a[66];
int e;
int main()
{
// freopen("b.in","r",stdin);
scanf("%I64d%I64d%I64d",&n,&l,&r);
if(n==0)
{
puts("0");
return 0;
}
while(n)
{
a[++e]=n%2ll;
n/=2ll;
}
ll j=1;
int ans=0;
for(int i=e;i;--i)
{
if(a[i])
{
ll L=(l-j)/(j*2)+((l-j)%(j*2)!=0);
if(l<j) L=0ll;
ll R=(r-j)/(j*2);
if(r<j) R=-1ll;
ans+=(int)(R-L+1ll);
}
j*=2ll;
}
printf("%d\n",ans);
return 0;
}