$\quad $ 想不出来了,遂打表。
$\quad $ 受到了luobotianle的启发,就依据其建议学上了分块打表。
如0与1的熟练
$\quad $ 问 \(L\) 到 \(R\) 之间,在二进制表示下(无前导\(0\)),\(0\) 的个数比 \(1\) 的个数多的数的个数。
$\quad $ 那么我们就可以以 \(5e5\) 为块长来打表。
打表程序
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
const int N=32,p=5e5;
bitset<N>bit;
int l,r,ans,ansl=0,cntl=0;
int main(){
freopen("biao.out","w",stdout);
for(register int i=1;i<=2e9;i=-~i){
bit=i;int cnt=0;
int le=ceil(log2(i))+(ceil(log2(i))==log2(i));
for(int j=0;j<=le-1;j=-~j)if(bit[j]&&((++cnt)<<1>le))break;
if((cnt<<1)<=le)ans++;
if(!(i%p)){
printf("%d,",ans-ansl),ansl=ans;
if(++cntl==40)putchar('\n'),cntl=0;//每40个数换行,方便观看。
}
}
return yhl;
}
码
#define yhl 0
#include"bits/stdc++.h"
using namespace std;
const int N=5e5;
bitset<33>bit;
int biao[4005]={
//此处省略100行打表代码
};
int l,r,ans;
bool check(int x){
if(!x)return 0;
int le=ceil(log2(x))+(ceil(log2(x))==log2(x));
bit=x;int cnt=0;
for(int i=0;i<le;i++)if(!bit[i])cnt++;
return ((cnt<<1)>=le);
}
int main(){
scanf("%d%d",&l,&r);
int bl=(l-1)/N+1,br=(r-1)/N+1;
if(bl^br){
for(int j=bl+1;j<=br-1;j++)ans+=biao[j];
for(int j=l;j<=bl*N;j++)ans+=check(j);
for(int j=br*N-N+1;j<=r;j++)ans+=check(j);
}else for(int i=l;i<=r;i++)ans+=check(i);
printf("%d",ans);
return yhl;
}