题目
思路
设
f
i
,
j
f_{i,j}
fi,j为前i个二进制位有j个(含前导0)0的个数。
f
i
,
j
=
f
i
−
1
,
j
−
1
+
f
i
−
1
,
j
(
1
<
=
i
<
=
31
,
1
<
=
j
<
=
i
,
f
i
,
0
=
1
)
f_{i,j}=f_{i-1,j-1}+f_{i-1,j}(1<=i<=31,1<=j<=i,f_{i,0}=1)
fi,j=fi−1,j−1+fi−1,j(1<=i<=31,1<=j<=i,fi,0=1)
利用上式优化区间求圆数过程,设为
s
(
x
)
s(x)
s(x)
然后把l~ r变成
s
(
r
)
−
s
(
l
−
1
)
s( r )-s( l-1 )
s(r)−s(l−1)即可
code:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<iomanip>
using namespace std;
int l,r,pw[35],f[35][35];
int kyx(int r)
{
if (r==0) return 0;
int tot=0,x=0,y=0,ans=0;
for (int i=1;i<=31&&r;i++) pw[++tot]=r%2,r/=2;
for (int pos=tot;pos>=1;pos--)
{
if (pw[pos]&&pos!=tot)
{
x++;
for (int i=0;i<pos;i++) if (x+i>=tot-x-i) ans+=f[pos-1][i];
x--;
}
if (pos!=tot)
{
for (int i=0;i<pos;i++) if (i>=pos-i) ans+=f[pos-1][i];
}
x+=1-pw[pos];
y+=pw[pos];
}
if (x>=y) ans++;
return ans;
}
int main()
{
cin>>l>>r;
for (int i=1;i<=31;i++) for (int j=1;j<=i;j++)
{
f[i-1][0]=1;
f[i][j]=f[i-1][j-1]+f[i-1][j];
}
cout<<kyx(r)-kyx(l-1);
return 0;
}